"""Database resource for Worqhat SDK."""

from typing import TYPE_CHECKING, Optional, Dict, Any, List, Union

if TYPE_CHECKING:
    from ..http_client import HTTPClient


class DatabaseResource:
    """Database operations resource."""

    def __init__(self, client: "HTTPClient"):
        """Initialize the database resource."""
        self._client = client

    def execute_query(
        self,
        query: str,
        params: Optional[Union[Dict[str, Any], List[Any]]] = None,
        environment: str = "production",
    ) -> Dict[str, Any]:
        """
        Execute a raw SQL query with named or positional parameters.

        Args:
            query: SQL query string.
            params: Named (dict) or positional (list) parameters.
            environment: Database environment (default: 'production').

        Returns:
            Query response with data and execution time.
        """
        payload: Dict[str, Any] = {"query": query}
        if params:
            payload["params"] = params
        if environment:
            payload["environment"] = environment

        return self._client.post("/api/db/query", json=payload)

    def query(
        self,
        query: str,
        params: Optional[Union[Dict[str, Any], List[Any]]] = None,
        environment: str = "production",
    ) -> Dict[str, Any]:
        """Alias for execute_query."""
        return self.execute_query(query, params, environment)

    def insert(
        self,
        table: str,
        data: Union[Dict[str, Any], List[Dict[str, Any]]],
        environment: str = "production",
    ) -> Dict[str, Any]:
        """
        Insert data into a table.

        Args:
            table: Table name.
            data: Single record (dict) or multiple records (list of dicts).
            environment: Database environment.

        Returns:
            Insert response with inserted data.
        """
        payload = {"table": table, "data": data, "environment": environment}
        return self._client.post("/api/db/insert", json=payload)

    def update(
        self,
        table: str,
        data: Dict[str, Any],
        where: Dict[str, Any],
        environment: str = "production",
    ) -> Dict[str, Any]:
        """
        Update data in a table.

        Args:
            table: Table name.
            data: Fields to update.
            where: WHERE conditions.
            environment: Database environment.

        Returns:
            Update response with updated records.
        """
        payload = {"table": table, "data": data, "where": where, "environment": environment}
        return self._client.put("/api/db/update", json=payload)

    def delete(
        self, table: str, where: Dict[str, Any], environment: str = "production"
    ) -> Dict[str, Any]:
        """
        Delete data from a table.

        Args:
            table: Table name.
            where: WHERE conditions.
            environment: Database environment.

        Returns:
            Delete response with deleted records.
        """
        payload = {"table": table, "where": where, "environment": environment}
        return self._client.delete("/api/db/delete", json=payload)

    def list_tables(
        self, environment: str = "production", schema: str = "public"
    ) -> Dict[str, Any]:
        """
        List all available tables in a schema.

        Args:
            environment: Database environment.
            schema: Schema name.

        Returns:
            List of tables.
        """
        params = {"environment": environment, "schema": schema}
        return self._client.get("/api/db/tables", params=params)

    def get_table_schema(
        self, table_name: str, environment: str = "production"
    ) -> Dict[str, Any]:
        """
        Get detailed schema information for a table.

        Args:
            table_name: Table name.
            environment: Database environment.

        Returns:
            Table schema with columns, indexes, and constraints.
        """
        params = {"environment": environment}
        return self._client.get(f"/api/db/tables/{table_name}/schema", params=params)

    def get_table_count(
        self,
        table_name: str,
        filters: Optional[Dict[str, Any]] = None,
        environment: str = "production",
    ) -> Dict[str, Any]:
        """
        Get row count for a table with optional filters.

        Args:
            table_name: Table name.
            filters: Optional WHERE conditions.
            environment: Database environment.

        Returns:
            Count response.
        """
        params: Dict[str, Any] = {"environment": environment}
        if filters:
            params.update(filters)

        return self._client.get(f"/api/db/tables/{table_name}/count", params=params)

    def batch(
        self,
        operations: List[Dict[str, Any]],
        environment: str = "production",
        transactional: bool = True,
    ) -> Dict[str, Any]:
        """
        Execute multiple operations in a single transaction.

        Args:
            operations: List of operations to execute.
            environment: Database environment.
            transactional: Whether to use a transaction.

        Returns:
            Batch response with results for each operation.
        """
        payload = {
            "operations": operations,
            "environment": environment,
            "transactional": transactional,
        }
        return self._client.post("/api/db/batch", json=payload)

    def semantic_search(
        self,
        query: str,
        table: Optional[str] = None,
        tables: Optional[List[str]] = None,
        limit: int = 10,
        threshold: float = 0.7,
        filters: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """
        Perform semantic similarity search using vector embeddings.

        Args:
            query: Search query.
            table: Single table name (mutually exclusive with tables).
            tables: Multiple table names for cross-table search.
            limit: Maximum number of results.
            threshold: Minimum similarity score.
            filters: Additional WHERE clause filters.

        Returns:
            Search results with similarity scores.
        """
        payload: Dict[str, Any] = {"query": query, "limit": limit, "threshold": threshold}

        if table:
            payload["table"] = table
        if tables:
            payload["tables"] = tables
        if filters:
            payload["filters"] = filters

        return self._client.post("/api/db/semantic-search", json=payload)

    def hybrid_search(
        self,
        query: str,
        table: str,
        text_columns: Optional[List[str]] = None,
        semantic_weight: float = 0.7,
        keyword_weight: float = 0.3,
        limit: int = 10,
    ) -> Dict[str, Any]:
        """
        Perform hybrid search combining semantic similarity with keyword search.

        Args:
            query: Search query.
            table: Table name.
            text_columns: Columns to search for keywords.
            semantic_weight: Weight for semantic score.
            keyword_weight: Weight for keyword score.
            limit: Maximum number of results.

        Returns:
            Search results with combined scores.
        """
        payload: Dict[str, Any] = {
            "query": query,
            "table": table,
            "semantic_weight": semantic_weight,
            "keyword_weight": keyword_weight,
            "limit": limit,
        }

        if text_columns:
            payload["text_columns"] = text_columns

        return self._client.post("/api/db/hybrid-search", json=payload)

    def find_similar(
        self,
        table: str,
        record_id: Union[str, int],
        limit: int = 10,
        threshold: Optional[float] = None,
        exclude_self: bool = True,
        target_table: Optional[str] = None,
    ) -> Dict[str, Any]:
        """
        Find records similar to a specific record using its embedding.

        Args:
            table: Source table name.
            record_id: ID of the source record.
            limit: Maximum number of similar records.
            threshold: Minimum similarity score.
            exclude_self: Whether to exclude the source record from results.
            target_table: Table to search in (defaults to same as table).

        Returns:
            Similar records with similarity scores.
        """
        payload: Dict[str, Any] = {
            "table": table,
            "record_id": record_id,
            "limit": limit,
            "exclude_self": exclude_self,
        }

        if threshold is not None:
            payload["threshold"] = threshold
        if target_table:
            payload["target_table"] = target_table

        return self._client.post("/api/db/find-similar", json=payload)
