# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""This module supports physical and logical plans in DataFusion."""

from __future__ import annotations

import warnings
from typing import TYPE_CHECKING, Any, Literal

import datafusion._internal as df_internal

if TYPE_CHECKING:
    import datetime

    from datafusion.context import SessionContext

__all__ = [
    "ExecutionPlan",
    "LogicalPlan",
    "Metric",
    "MetricsSet",
    "PhysicalPartitioning",
]


class LogicalPlan:  # noqa: PLW1641
    """Logical Plan.

    A `LogicalPlan` is a node in a tree of relational operators (such as
    Projection or Filter).

    Represents transforming an input relation (table) to an output relation
    (table) with a potentially different schema. Plans form a dataflow tree
    where data flows from leaves up to the root to produce the query result.

    A `LogicalPlan` can be created by the SQL query planner, the DataFrame API,
    or programmatically (for example custom query languages).
    """

    def __init__(self, plan: df_internal.LogicalPlan) -> None:
        """This constructor should not be called by the end user."""
        self._raw_plan = plan

    def to_variant(self) -> Any:
        """Convert the logical plan into its specific variant."""
        return self._raw_plan.to_variant()

    def inputs(self) -> list[LogicalPlan]:
        """Returns the list of inputs to the logical plan."""
        return [LogicalPlan(p) for p in self._raw_plan.inputs()]

    def __repr__(self) -> str:
        """Generate a printable representation of the plan."""
        return self._raw_plan.__repr__()

    def display(self) -> str:
        """Print the logical plan."""
        return self._raw_plan.display()

    def display_indent(self) -> str:
        """Print an indented form of the logical plan."""
        return self._raw_plan.display_indent()

    def display_indent_schema(self) -> str:
        """Print an indented form of the schema for the logical plan."""
        return self._raw_plan.display_indent_schema()

    def display_graphviz(self) -> str:
        """Print the graph visualization of the logical plan.

        Returns a formattable structure that produces lines meant for graphical
        display using the ``DOT`` language. This format can be visualized using
        software from `graphviz <https://graphviz.org/>`_.
        """
        return self._raw_plan.display_graphviz()

    @staticmethod
    def from_bytes(ctx: SessionContext, data: bytes) -> LogicalPlan:
        """Create a LogicalPlan from serialized protobuf bytes.

        Decoding routes through the codecs installed on ``ctx`` with
        :py:meth:`~datafusion.SessionContext.with_logical_extension_codec`.
        Tables created in memory from record batches are currently not
        supported.

        Unlike :py:meth:`datafusion.Expr.from_bytes`, ``ctx`` is required and
        positional, and there is no fallback to a worker or global context.

        See Also:
            :py:meth:`to_bytes`, :py:meth:`ExecutionPlan.from_bytes`,
            :py:meth:`datafusion.Expr.from_bytes`.
        """
        return LogicalPlan(df_internal.LogicalPlan.from_bytes(ctx.ctx, data))

    def to_bytes(self, ctx: SessionContext | None = None) -> bytes:
        """Convert a LogicalPlan to serialized protobuf bytes.

        When ``ctx`` is supplied, encoding routes through the codecs
        installed on it with
        :py:meth:`~datafusion.SessionContext.with_logical_extension_codec`,
        so extension codecs see the encode path. With ``ctx=None`` a
        default codec is used. Tables created in memory from record
        batches are currently not supported.

        See Also:
            :py:meth:`from_bytes`, :py:meth:`ExecutionPlan.to_bytes`,
            :py:meth:`datafusion.Expr.to_bytes`.
        """
        ctx_arg = ctx.ctx if ctx is not None else None
        return self._raw_plan.to_bytes(ctx_arg)

    @staticmethod
    def from_proto(ctx: SessionContext, data: bytes) -> LogicalPlan:
        """Deprecated alias for :meth:`from_bytes`."""
        warnings.warn(
            "LogicalPlan.from_proto is deprecated; use from_bytes instead",
            DeprecationWarning,
            stacklevel=2,
        )
        return LogicalPlan.from_bytes(ctx, data)

    def to_proto(self) -> bytes:
        """Deprecated alias for :meth:`to_bytes`."""
        warnings.warn(
            "LogicalPlan.to_proto is deprecated; use to_bytes instead",
            DeprecationWarning,
            stacklevel=2,
        )
        return self.to_bytes()

    def __eq__(self, other: LogicalPlan) -> bool:
        """Test equality."""
        if not isinstance(other, LogicalPlan):
            return False
        return self._raw_plan.__eq__(other._raw_plan)


class ExecutionPlan:
    """Represent nodes in the DataFusion Physical Plan."""

    def __init__(self, plan: df_internal.ExecutionPlan) -> None:
        """This constructor should not be called by the end user."""
        self._raw_plan = plan

    def children(self) -> list[ExecutionPlan]:
        """Get a list of children ``ExecutionPlan`` that act as inputs to this plan.

        The returned list will be empty for leaf nodes such as scans, will contain a
        single value for unary nodes, or two values for binary nodes (such as joins).
        """
        return [ExecutionPlan(e) for e in self._raw_plan.children()]

    def display(self) -> str:
        """Print the physical plan."""
        return self._raw_plan.display()

    def display_indent(self) -> str:
        """Print an indented form of the physical plan."""
        return self._raw_plan.display_indent()

    def __repr__(self) -> str:
        """Print a string representation of the physical plan."""
        return self._raw_plan.__repr__()

    @property
    def partition_count(self) -> int:
        """Returns the number of partitions in the physical plan.

        Examples:
            >>> from datafusion import SessionContext
            >>> ctx = SessionContext()
            >>> df = ctx.from_pydict({"a": [1, 2, 3]})
            >>> df.execution_plan().partition_count
            1
        """
        return self._raw_plan.partition_count

    @property
    def output_partitioning(self) -> PhysicalPartitioning:
        """Returns how this plan's output rows are spread across its partitions.

        Where :py:attr:`partition_count` gives only the number of partitions,
        this also reports the scheme, so a caller executing partitions
        separately can tell whether they are hash-distributed on known keys or
        merely counted. A plan does not necessarily partition the way it was
        asked to; see :ref:`checking_partitioning`.

        Examples:
            >>> import pyarrow as pa
            >>> from datafusion import SessionConfig, SessionContext
            >>> ctx = SessionContext(SessionConfig().with_target_partitions(4))
            >>> ctx.register_record_batches("t", [
            ...     [pa.record_batch({"a": [1, 2, 3]})],
            ...     [pa.record_batch({"a": [4, 5, 6]})],
            ... ])
            >>> ctx.sql("select a from t").execution_plan().output_partitioning
            UnknownPartitioning(2)

            A group-by redistributes rows, so the plan reports the keys:

            >>> grouped = ctx.sql("select a, count(*) from t group by a")
            >>> partitioning = grouped.execution_plan().output_partitioning
            >>> partitioning.scheme
            'Hash'
            >>> partitioning.partition_count
            4
        """
        return PhysicalPartitioning(self._raw_plan.output_partitioning)

    @staticmethod
    def from_bytes(ctx: SessionContext, data: bytes) -> ExecutionPlan:
        """Create an ExecutionPlan from serialized protobuf bytes.

        Decoding routes through the codecs installed on ``ctx`` with
        :py:meth:`~datafusion.SessionContext.with_physical_extension_codec`.

        Unlike :py:meth:`datafusion.Expr.from_bytes`, ``ctx`` is required and
        positional, and there is no fallback to a worker or global context.
        ``ctx`` need share nothing with the session that encoded the plan: a
        scan over a table registered from record batches decodes here, because
        the batches travel inside the encoded scan.

        See Also:
            :py:meth:`to_bytes`, :py:meth:`LogicalPlan.from_bytes`.
        """
        return ExecutionPlan(df_internal.ExecutionPlan.from_bytes(ctx.ctx, data))

    def to_bytes(self, ctx: SessionContext | None = None) -> bytes:
        """Convert an ExecutionPlan into serialized protobuf bytes.

        When ``ctx`` is supplied, encoding routes through the codecs
        installed on it with
        :py:meth:`~datafusion.SessionContext.with_physical_extension_codec`.

        Unlike :py:meth:`LogicalPlan.to_bytes`, a plan reading a table
        registered from record batches does round-trip: the batches travel
        inside the encoded scan.

        Round-tripping through this method and :py:meth:`from_bytes` is how
        an extension library checks that its own codec claimed its nodes,
        rather than a codec installed earlier in the chain — see
        :ref:`extension_codec_order`.

        See Also:
            :py:meth:`from_bytes`, :py:meth:`LogicalPlan.to_bytes`.
        """
        ctx_arg = ctx.ctx if ctx is not None else None
        return self._raw_plan.to_bytes(ctx_arg)

    @staticmethod
    def from_proto(ctx: SessionContext, data: bytes) -> ExecutionPlan:
        """Deprecated alias for :meth:`from_bytes`."""
        warnings.warn(
            "ExecutionPlan.from_proto is deprecated; use from_bytes instead",
            DeprecationWarning,
            stacklevel=2,
        )
        return ExecutionPlan.from_bytes(ctx, data)

    def to_proto(self) -> bytes:
        """Deprecated alias for :meth:`to_bytes`."""
        warnings.warn(
            "ExecutionPlan.to_proto is deprecated; use to_bytes instead",
            DeprecationWarning,
            stacklevel=2,
        )
        return self.to_bytes()

    def metrics(self) -> MetricsSet | None:
        """Return metrics for this plan node, or None if this plan has no MetricsSet.

        Some operators (e.g. DataSourceExec) eagerly initialize a MetricsSet
        when the plan is created, so this may return a set even before
        execution.  Metric *values* (such as ``output_rows``) are only
        meaningful after the DataFrame has been executed.
        """
        raw = self._raw_plan.metrics()
        if raw is None:
            return None
        return MetricsSet(raw)

    def collect_metrics(self) -> list[tuple[str, MetricsSet]]:
        """Return runtime statistics for each step of the query execution.

        DataFusion executes a query as a pipeline of operators — for example a
        data source scan, followed by a filter, followed by a projection. After
        the DataFrame has been executed (via
        :py:meth:`~datafusion.DataFrame.collect`,
        :py:meth:`~datafusion.DataFrame.execute_stream`, etc.), each operator
        records statistics such as how many rows it produced and how much CPU
        time it consumed.

        Each entry in the returned list corresponds to one operator that
        recorded metrics. The first element of the tuple is the operator's
        description string — the same text shown by
        :py:meth:`display_indent` — which identifies both the operator type
        and its key parameters, for example ``"FilterExec: column1@0 > 1"``
        or ``"DataSourceExec: partitions=1"``.

        Returns:
            A list of ``(description, MetricsSet)`` tuples ordered from the
            outermost operator (top of the execution tree) down to the
            data-source leaves. Only operators that recorded at least one
            metric are included. Returns an empty list if called before the
            DataFrame has been executed.
        """
        result: list[tuple[str, MetricsSet]] = []

        def _walk(node: ExecutionPlan) -> None:
            ms = node.metrics()
            if ms is not None:
                result.append((node.display(), ms))
            for child in node.children():
                _walk(child)

        _walk(self)
        return result


class PhysicalPartitioning:
    """How a physical plan's output rows are spread across its partitions.

    Returned by :py:attr:`ExecutionPlan.output_partitioning`. This is the
    partitioning a built plan *has*. Distinct from
    :py:class:`datafusion.expr.Partitioning`, the *logical* partitioning a
    ``Repartition`` node records and hands back from
    ``partitioning_scheme()`` — a request, which the plan need not honour. See
    :ref:`checking_partitioning`.
    """

    def __init__(self, partitioning: df_internal.PhysicalPartitioning) -> None:
        """This constructor should not be called by the end user."""
        self._raw_partitioning = partitioning

    @property
    def scheme(
        self,
    ) -> Literal["RoundRobinBatch", "Hash", "Range", "UnknownPartitioning"]:
        """Which partitioning scheme this is.

        ``"UnknownPartitioning"`` means the plan knows how many partitions it
        has but nothing about how rows are distributed between them, which is
        the usual case for a file scan. ``"RoundRobinBatch"`` and ``"Hash"``
        come from a repartition the optimizer inserted. ``"Range"`` only
        appears on a plan this package did not build; see
        :ref:`checking_partitioning`.

        Examples:
            >>> from datafusion import SessionContext
            >>> ctx = SessionContext()
            >>> df = ctx.from_pydict({"a": [1, 2, 3]})
            >>> df.execution_plan().output_partitioning.scheme
            'UnknownPartitioning'
        """
        return self._raw_partitioning.scheme

    @property
    def partition_count(self) -> int:
        """The number of partitions.

        Examples:
            >>> from datafusion import SessionContext
            >>> ctx = SessionContext()
            >>> df = ctx.from_pydict({"a": [1, 2, 3]})
            >>> df.execution_plan().output_partitioning.partition_count
            1
        """
        return self._raw_partitioning.partition_count

    @property
    def hash_expressions(self) -> list[str] | None:
        """The expressions rows are hashed on, or ``None`` for other schemes.

        Physical expressions have no Python representation, so these are
        returned in their displayed form. ``None`` covers ``"Range"`` as well,
        whose ordering and split points this class does not expose.

        Examples:
            >>> import pyarrow as pa
            >>> from datafusion import SessionConfig, SessionContext
            >>> ctx = SessionContext(SessionConfig().with_target_partitions(4))
            >>> ctx.register_record_batches("t", [
            ...     [pa.record_batch({"a": [1, 2, 3]})],
            ...     [pa.record_batch({"a": [4, 5, 6]})],
            ... ])
            >>> scan = ctx.sql("select a from t").execution_plan()
            >>> scan.output_partitioning.hash_expressions is None
            True
            >>> grouped = ctx.sql("select a, count(*) from t group by a")
            >>> grouped.execution_plan().output_partitioning.hash_expressions
            ['a@0']
        """
        return self._raw_partitioning.hash_expressions

    def __repr__(self) -> str:
        """Print a string representation of the partitioning.

        Examples:
            >>> from datafusion import SessionContext
            >>> ctx = SessionContext()
            >>> df = ctx.from_pydict({"a": [1, 2, 3]})
            >>> repr(df.execution_plan().output_partitioning)
            'UnknownPartitioning(1)'
        """
        return self._raw_partitioning.__repr__()

    def _key(self) -> tuple[str, int, tuple[str, ...] | None]:
        exprs = self.hash_expressions
        return (self.scheme, self.partition_count, tuple(exprs) if exprs else None)

    def __eq__(self, other: object) -> bool:
        """Compare two partitionings by scheme, count and hash expressions.

        Equality is structural, and does not mirror DataFusion's own
        comparison of the underlying type, under which two
        ``UnknownPartitioning`` values of the same width are unequal.

        Examples:
            >>> from datafusion import SessionContext
            >>> ctx = SessionContext()
            >>> a = ctx.from_pydict({"a": [1, 2, 3]}).execution_plan()
            >>> b = ctx.from_pydict({"b": [4, 5, 6]}).execution_plan()
            >>> a.output_partitioning == b.output_partitioning
            True
            >>> a.output_partitioning == "UnknownPartitioning(1)"
            False
        """
        if not isinstance(other, PhysicalPartitioning):
            return NotImplemented
        return self._key() == other._key()

    def __hash__(self) -> int:
        """Hash the partitioning, consistently with :py:meth:`__eq__`.

        Examples:
            >>> from datafusion import SessionContext
            >>> ctx = SessionContext()
            >>> a = ctx.from_pydict({"a": [1, 2, 3]}).execution_plan()
            >>> b = ctx.from_pydict({"b": [4, 5, 6]}).execution_plan()
            >>> len({a.output_partitioning, b.output_partitioning})
            1
        """
        return hash(self._key())


class MetricsSet:
    """A set of metrics for a single execution plan operator.

    A physical plan operator runs independently across one or more partitions.
    :py:meth:`metrics` returns the raw per-partition :py:class:`Metric` objects.
    The convenience properties (:py:attr:`output_rows`, :py:attr:`elapsed_compute`,
    etc.) automatically sum the named metric across *all* partitions, giving a
    single aggregate value for the operator as a whole.
    """

    def __init__(self, raw: df_internal.MetricsSet) -> None:
        """This constructor should not be called by the end user."""
        self._raw = raw

    def metrics(self) -> list[Metric]:
        """Return all individual metrics in this set."""
        return [Metric(m) for m in self._raw.metrics()]

    @property
    def output_rows(self) -> int | None:
        """Sum of output_rows across all partitions."""
        return self._raw.output_rows()

    @property
    def elapsed_compute(self) -> int | None:
        """Total CPU time (in nanoseconds) spent inside this operator's execute loop.

        Summed across all partitions. Returns ``None`` if no ``elapsed_compute``
        metric was recorded.
        """
        return self._raw.elapsed_compute()

    @property
    def spill_count(self) -> int | None:
        """Number of times this operator spilled data to disk due to memory pressure.

        This is a count of spill events, not a byte count. Summed across all
        partitions. Returns ``None`` if no ``spill_count`` metric was recorded.
        """
        return self._raw.spill_count()

    @property
    def spilled_bytes(self) -> int | None:
        """Sum of spilled_bytes across all partitions."""
        return self._raw.spilled_bytes()

    @property
    def spilled_rows(self) -> int | None:
        """Sum of spilled_rows across all partitions."""
        return self._raw.spilled_rows()

    def sum_by_name(self, name: str) -> int | None:
        """Sum the named metric across all partitions.

        Useful for accessing any metric not exposed as a first-class property.
        Returns ``None`` if no metric with the given name was recorded.

        Args:
            name: The metric name, e.g. ``"output_rows"`` or ``"elapsed_compute"``.
        """
        return self._raw.sum_by_name(name)

    def __repr__(self) -> str:
        """Return a string representation of the metrics set."""
        return repr(self._raw)


class Metric:
    """A single execution metric with name, value, partition, and labels."""

    def __init__(self, raw: df_internal.Metric) -> None:
        """This constructor should not be called by the end user."""
        self._raw = raw

    @property
    def name(self) -> str:
        """The name of this metric (e.g. ``output_rows``)."""
        return self._raw.name

    @property
    def value(self) -> int | datetime.datetime | None:
        """The value of this metric.

        Returns an ``int`` for counters, gauges, and time-based metrics
        (nanoseconds), a :py:class:`~datetime.datetime` (UTC) for
        ``start_timestamp`` / ``end_timestamp`` metrics, or ``None``
        when the value has not been set or is not representable.
        """
        return self._raw.value

    @property
    def value_as_datetime(self) -> datetime.datetime | None:
        """The value as a UTC :py:class:`~datetime.datetime` for timestamp metrics.

        Returns ``None`` for all non-timestamp metrics and for timestamp
        metrics whose value has not been set (e.g. before execution).
        """
        return self._raw.value_as_datetime

    @property
    def partition(self) -> int | None:
        """The 0-based partition index this metric applies to.

        Returns ``None`` for metrics that are not partition-specific (i.e. they
        apply globally across all partitions of the operator).
        """
        return self._raw.partition

    def labels(self) -> dict[str, str]:
        """Return the labels associated with this metric.

        Labels provide additional context for a metric.  For example::

            metric.labels()
            # {'output_type': 'final'}
        """
        return self._raw.labels()

    def __repr__(self) -> str:
        """Return a string representation of the metric."""
        return repr(self._raw)
