# 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.

"""Coordinate search execution and transport without coupling the backends.

The selected backend consumes ordinary snapshot-and-split plans, including
transported plans. An execution error never triggers another search.
"""

from contextlib import contextmanager
from copy import copy
from functools import partial
from threading import local


_search_execution = local()


@contextmanager
def _python_search_execution():
    """Retain Python selection through hooks delegating to public methods."""
    previous = getattr(_search_execution, 'python', False)
    _search_execution.python = True
    try:
        yield
    finally:
        _search_execution.python = previous


def _python_search_request(request):
    if getattr(_search_execution, 'python', False):
        request = copy(request)
        request._table = request._table.copy_without_time_travel({
            'read.native.enabled': 'false', 'scan.native-plan.enabled': 'false'})
    return request


def _python_vector_scan(execution):
    from pypaimon.execution.python.read.search.factories import new_vector_scan
    return new_vector_scan(_python_search_request(execution))


def _python_vector_read(builder, batch):
    from pypaimon.execution.python.read.search.factories import new_batch_vector_read, new_vector_read
    builder = _python_search_request(builder)
    return new_batch_vector_read(builder) if batch else new_vector_read(builder)


def _python_full_text_scan(execution):
    from pypaimon.execution.python.read.search.factories import new_full_text_scan
    return new_full_text_scan(_python_search_request(execution))


def _python_full_text_read(execution):
    from pypaimon.execution.python.read.search.factories import new_full_text_read
    return new_full_text_read(_python_search_request(execution))


class _SearchScan:
    def __init__(self, native, python_factory):
        self._native_scan = native
        self._python_factory = python_factory
        self._python_executor = None

    def scan(self):
        if self._native_scan.available():
            return self._native_scan.scan()
        if self._python_executor is None:
            self._python_executor = self._python_factory()
        return self._python_executor.scan()


class _SearchRead:
    def __init__(self, native, python_factory):
        self._native_reader = native
        self._python_factory = python_factory
        self._python_executor = None

    def _python_reader(self):
        if self._python_executor is None:
            self._python_executor = self._python_factory()
        return self._python_executor

    def read_plan(self, plan, executor=None):
        return (self._native_reader.read_plan(plan) if executor is None else
                self._native_reader.read_plan(plan, executor=executor))

    def read_batch_plan(self, plan, executor=None):
        return (self._native_reader.read_batch_plan(plan) if executor is None else
                self._native_reader.read_batch_plan(plan, executor=executor))


class _SplitSearchRead(_SearchRead):
    def read(self, splits):
        return self._native_reader.read(splits)


class _BatchSearchRead(_SearchRead):
    def read_batch(self, splits):
        return self._native_reader.read_batch(splits)


def python_search_reader(reader):
    """Select Python explicitly for backend parity and transported-plan checks."""
    return reader._python_reader() if isinstance(reader, _SearchRead) else reader


def _native_requested(builder):
    if getattr(_search_execution, 'python', False):
        return False
    table = getattr(builder, '_table', None)
    enabled = getattr(getattr(table, 'options', None), 'native_read_enabled', None)
    return callable(enabled) and enabled()


def create_vector_scan(builder, execution, batch=False):
    python_factory = partial(_python_vector_scan, execution)
    if not _native_requested(builder):
        return python_factory()
    from pypaimon.execution.native.read.native_search_plan import native_vector_scan
    native = native_vector_scan(builder, batch)
    return python_factory() if native is None else _SearchScan(native, python_factory)


def create_vector_read(builder, batch=False):
    python_factory = partial(_python_vector_read, builder, batch)
    if not _native_requested(builder):
        return python_factory()
    from pypaimon.execution.native.read.native_search_plan import native_vector_read
    native = native_vector_read(builder, batch)
    if native is None:
        return python_factory()
    reader_type = _BatchSearchRead if batch else _SplitSearchRead
    return reader_type(native, python_factory)


def create_full_text_scan(builder, execution):
    python_factory = partial(_python_full_text_scan, execution)
    if not _native_requested(builder):
        return python_factory()
    from pypaimon.execution.native.read.native_search_plan import native_full_text_scan
    native = native_full_text_scan(builder)
    return python_factory() if native is None else _SearchScan(native, python_factory)


def create_full_text_read(builder, execution):
    python_factory = partial(_python_full_text_read, execution)
    if not _native_requested(builder):
        return python_factory()
    from pypaimon.execution.native.read.native_search_plan import native_full_text_read
    native = native_full_text_read(builder)
    return python_factory() if native is None else _SplitSearchRead(native, python_factory)


def execute_vector_search(builder, queries, batch=False):
    if _native_requested(builder):
        from pypaimon.execution.native.read.native_vector_search import try_native_vector_search
        result = try_native_vector_search(builder, queries, batch)
        if result is not None:
            return result
    reader = (builder.new_batch_vector_search_read() if batch
              else builder.new_vector_search_read())
    plan = builder.new_vector_search_scan().scan()
    return reader.read_batch_plan(plan) if batch else reader.read_plan(plan)


def execute_full_text_search(builder):
    if _native_requested(builder):
        from pypaimon.execution.native.read.native_full_text_search import try_native_full_text_search
        result = try_native_full_text_search(builder)
        if result is not None:
            return result
    return builder.new_full_text_read().read_plan(builder.new_full_text_scan().scan())


def _standard_hybrid_builder(builder):
    from pypaimon.table.source.hybrid_search_builder import HybridSearchBuilderImpl
    # Instance and subclass hooks own their execution protocol. Native cannot
    # replace them, and copying their owner would change observable side effects.
    return type(builder) is HybridSearchBuilderImpl and not any(name in vars(builder) for name in (
        'route_builders', 'to_route_result', 'rank', '_new_vector_search_builder', '_new_full_text_search_builder'))


def execute_hybrid_search(builder, executor=None):
    standard = _standard_hybrid_builder(builder)
    if standard and _native_requested(builder):
        from pypaimon.execution.native.read.native_hybrid_search import try_native_hybrid_search
        result = (try_native_hybrid_search(builder) if executor is None else
                  try_native_hybrid_search(builder, executor=executor))
        if result is not None:
            return result
    from pypaimon.execution.python.read.search.hybrid_search import execute
    return execute(builder, executor)


def hybrid_route_builders(builder):
    from pypaimon.catalog.table_query_auth import reject_search_under_query_auth
    # Authorization precedes runtime discovery and snapshot resolution, as in
    # Java's routeBuilders(). Selecting a backend must not hide a rejection.
    reject_search_under_query_auth(builder._table)
    if _native_requested(builder):
        from pypaimon.execution.native.read.native_hybrid_search import try_native_hybrid_routes
        routes = try_native_hybrid_routes(builder)
        if routes is not None:
            return routes
    from pypaimon.execution.python.read.search.hybrid_search import route_builders
    return route_builders(builder)


def rank_hybrid_results(builder, route_results):
    builder._validate_search()
    if _native_requested(builder):
        from pypaimon.execution.native.runtime import native_runtime_available
        if native_runtime_available():
            from pypaimon.execution.native.read.native_hybrid_search import rank_hybrid_results as rank
            return rank(builder, route_results)
    from pypaimon.execution.python.read.search.hybrid_search import rank
    return rank(builder, route_results)
