"""Type conversion utilities between gRPC proto types and Python types."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Dict, List

if TYPE_CHECKING:
    from ..response import Response, Row
    from ..types import (
        GraphInfo,
        GraphType,
        HealthStatus,
        PropertyType,
        TypedValue,
    )


def convert_gql_response(proto_response: Any) -> Response:
    """Convert gRPC response to Response object.

    Args:
        proto_response: Proto GqlResponse

    Returns:
        Response object
    """
    from ..response import Response, Row
    from ..types import PropertyType, TypedValue

    rows = []
    for proto_row in proto_response.rows:
        typed_values = []
        for proto_val in proto_row.values:
            tv = TypedValue(
                type=PropertyType(proto_val.type),
                data=proto_val.data,
                is_null=proto_val.is_null
            )
            typed_values.append(tv)
        rows.append(Row(values=typed_values))

    return Response(
        columns=list(proto_response.columns),
        rows=rows,
        row_count=proto_response.row_count,
        has_more=proto_response.has_more,
        warnings=list(proto_response.warnings),
        rows_affected=proto_response.rows_affected
    )


def convert_graph_info(proto_info: Any) -> GraphInfo:
    """Convert proto GraphInfo to Python GraphInfo.

    Args:
        proto_info: Proto GraphInfo

    Returns:
        GraphInfo object
    """
    from ..types import GraphInfo, GraphType

    return GraphInfo(
        name=proto_info.name,
        graph_type=GraphType(proto_info.graph_type),
        node_count=proto_info.node_count,
        edge_count=proto_info.edge_count,
        description=proto_info.description
    )


def convert_health_status(proto_status: int) -> HealthStatus:
    """Convert proto HealthStatus to enum.

    Args:
        proto_status: Proto health status value

    Returns:
        HealthStatus enum
    """
    from ..types import HealthStatus

    return HealthStatus(proto_status)


def node_data_to_proto(node: Any, proto_module: Any) -> Any:
    """Convert NodeData to proto format.

    Args:
        node: NodeData object
        proto_module: Proto module (gqldb_pb2)

    Returns:
        Proto NodeData
    """
    from ..types import create_typed_value

    properties = {}
    if hasattr(node, 'properties') and node.properties:
        for key, value in node.properties.items():
            properties[key] = create_typed_value(value, proto_module)

    return proto_module.NodeData(
        labels=node.labels if hasattr(node, 'labels') else [],
        properties=properties
    )


def edge_data_to_proto(edge: Any, proto_module: Any) -> Any:
    """Convert EdgeData to proto format.

    Args:
        edge: EdgeData object
        proto_module: Proto module (gqldb_pb2)

    Returns:
        Proto EdgeData
    """
    from ..types import create_typed_value

    properties = {}
    if hasattr(edge, 'properties') and edge.properties:
        for key, value in edge.properties.items():
            properties[key] = create_typed_value(value, proto_module)

    return proto_module.EdgeData(
        label=edge.label if hasattr(edge, 'label') else '',
        from_node_id=edge.from_node_id if hasattr(edge, 'from_node_id') else '',
        to_node_id=edge.to_node_id if hasattr(edge, 'to_node_id') else '',
        properties=properties
    )


def convert_proto_properties(proto_props: Dict[str, Any]) -> Dict[str, Any]:
    """Convert proto properties map to Python dict.

    Args:
        proto_props: Proto properties dict

    Returns:
        Python dict with decoded values
    """
    from ..types import PropertyType, TypedValue

    result = {}
    for key, proto_val in proto_props.items():
        tv = TypedValue(
            type=PropertyType(proto_val.type),
            data=proto_val.data,
            is_null=proto_val.is_null
        )
        result[key] = tv.to_python()
    return result
