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

"""Python global index file construction."""

import threading
from concurrent.futures import FIRST_EXCEPTION, ThreadPoolExecutor, wait
from functools import cmp_to_key
from typing import List, Optional, Union

import pyarrow as pa
import pyarrow.compute as pc

from pypaimon.execution.python.globalindex.btree.btree_index_writer import (
    BTREE_IDENTIFIER,
    BTreeIndexWriter,
)
from pypaimon.execution.python.globalindex.bitmap.bitmap_index_writer import (
    BITMAP_IDENTIFIER,
    BitmapIndexWriter,
)
from pypaimon.execution.python.globalindex.build_plan import (
    filter_non_indexable_splits as _filter_non_indexable_splits,
    split_by_contiguous_unindexed_row_range as _split_by_contiguous_unindexed_row_range,
    split_by_global_index_shard as _split_by_global_index_shard,
    unindexed_row_ranges as _unindexed_row_ranges,
)
from pypaimon.globalindex.global_index_meta import GlobalIndexMeta
from pypaimon.execution.python.globalindex.key_serializer import create_serializer
from pypaimon.globalindex.full_text_options import FULL_TEXT_IDENTIFIER
from pypaimon.execution.python.write.native_full_text_index_writer import NativeFullTextIndexWriter
from pypaimon.globalindex.vindex_options import VINDEX_IDENTIFIERS
from pypaimon.execution.python.globalindex.vindex.vindex_vector_index_writer import (
    ADD_BATCH_SIZE,
    VindexVectorIndexWriter,
)
from pypaimon.index.index_file_meta import IndexFileMeta
from pypaimon.index.data_evolution_index_source_meta import DataEvolutionIndexSourceMeta
from pypaimon.manifest.index_manifest_entry import IndexManifestEntry
from pypaimon.table.row.generic_row import GenericRow
from pypaimon.table.special_fields import SpecialFields
from pypaimon.utils.range import Range
from pypaimon.write.commit_message import CommitMessage


_SORTED_INDEX_IDENTIFIERS = (BTREE_IDENTIFIER, BITMAP_IDENTIFIER)
_GENERIC_INDEX_IDENTIFIERS = tuple(VINDEX_IDENTIFIERS) + (FULL_TEXT_IDENTIFIER,)
_SORTED_INDEX_RECORDS_PER_FILE_FLOATING = 1.2


class PythonGlobalIndexBuilder:
    """Algorithms invoked only by the Python index build path."""

    def __init__(self, request):
        self._table = request._table
        self._index_columns = list(request._index_columns)
        self._index_type = request._index_type
        self._options = request._options
        self._core_options = request._core_options
        self._user_options = dict(request._user_options)

    def build(self, partition_filter, *, execution="local", concurrency=None, ray_remote_args=None):
        read_builder = self._table.new_read_builder()
        if partition_filter is not None:
            read_builder = read_builder.with_partition_filter(partition_filter)

        scan = read_builder.new_scan()
        plan = scan.plan_all()
        splits = plan.splits()
        if not splits:
            return []

        index_field = self._table.field_dict[self._index_columns[0]]
        snapshot = self._snapshot_for_plan(plan)
        unindexed_ranges = _unindexed_row_ranges(
            self._table,
            snapshot,
            partition_filter,
            index_field.id,
            self._index_type,
        )
        if not unindexed_ranges:
            return []

        if self._index_type in _GENERIC_INDEX_IDENTIFIERS:
            splits = _filter_non_indexable_splits(
                self._table, splits, self._index_columns)
            if not splits:
                return []

        read_type = [index_field, SpecialFields.ROW_ID]
        from pypaimon.read.table_read import TableRead

        table_read = TableRead(
            table=self._table,
            predicate=None,
            read_type=read_type,
        )
        index_path_factory = self._table.path_factory().global_index_path_factory()
        index_path = index_path_factory.global_index_root_path()

        if self._index_type in _SORTED_INDEX_IDENTIFIERS:
            return self._build_sorted_index(
                splits, unindexed_ranges, index_field, table_read, index_path,
                DataEvolutionIndexSourceMeta(snapshot.id).serialize() if snapshot else None)
        if execution == "ray":
            from pypaimon.execution.python.globalindex.ray_index_build import build_vector_index
            return build_vector_index(
                self, splits, unindexed_ranges, index_field, table_read,
                index_path, concurrency, ray_remote_args)
        return self._build_generic_index(
            splits, unindexed_ranges, index_field, table_read, index_path)

    def _snapshot_for_plan(self, plan):
        snapshot_id = getattr(plan, "snapshot_id", None)
        snapshot_manager = self._table.snapshot_manager()
        if snapshot_id is not None:
            return snapshot_manager.get_snapshot_by_id(snapshot_id)
        return snapshot_manager.get_latest_snapshot()

    def _build_sorted_index(
        self, splits, unindexed_ranges, index_field, table_read, index_path: str,
        source_meta=None,
    ) -> List[CommitMessage]:
        key_serializer = create_serializer(index_field.type)
        configured_records_per_range = (
            self._core_options.sorted_index_records_per_range())
        if configured_records_per_range <= 0:
            raise ValueError("sorted-index.records-per-file must be positive.")
        records_per_range = int(
            configured_records_per_range
            * _SORTED_INDEX_RECORDS_PER_FILE_FLOATING
        )

        messages = []
        for split, row_range in _split_by_contiguous_unindexed_row_range(
            splits, unindexed_ranges
        ):
            table = table_read.to_arrow([split])
            if table is None or table.num_rows == 0:
                continue
            rows = _extract_sorted_rows(
                table,
                self._index_columns[0],
                SpecialFields.ROW_ID.name,
                key_serializer,
                row_range,
            )
            if not rows:
                continue
            index_adds = []
            for chunk in _chunks(rows, records_per_range):
                writer = self._create_sorted_index_writer(
                    index_path, key_serializer)
                for key, row_id in chunk:
                    writer.write(key, row_id - row_range.from_)
                result_entries = writer.finish()
                index_adds.extend(
                    _to_index_manifest_entries(
                        self._table,
                        split.partition,
                        row_range,
                        index_field.id,
                        self._index_type,
                        result_entries,
                        source_meta=source_meta,
                    )
                )
            if index_adds:
                messages.append(
                    CommitMessage(
                        partition=tuple(split.partition.values),
                        bucket=0,
                        new_files=[],
                        index_adds=index_adds,
                    )
                )
        return messages

    def _create_sorted_index_writer(self, index_path: str, key_serializer):
        if self._index_type == BTREE_IDENTIFIER:
            return BTreeIndexWriter(
                self._table.file_io,
                index_path,
                key_serializer,
                block_size=self._core_options.btree_index_block_size(),
                bloom_filter_enabled=(
                    self._core_options.btree_index_bloom_filter_enabled()),
            )
        if self._index_type == BITMAP_IDENTIFIER:
            return BitmapIndexWriter(
                self._table.file_io,
                index_path,
                key_serializer,
                dictionary_block_size=(
                    self._core_options.bitmap_index_dictionary_block_size()),
                compression=self._core_options.bitmap_index_compression(),
            )
        raise ValueError("Unsupported sorted global index type: %s" % self._index_type)

    def _build_generic_index(
        self, splits, unindexed_ranges, index_field, table_read, index_path: str
    ) -> List[CommitMessage]:
        rows_per_shard = self._core_options.global_index_row_count_per_shard()
        if rows_per_shard <= 0:
            raise ValueError(
                "Option 'global-index.row-count-per-shard' must be greater than 0."
            )

        parallelism = self._core_options.global_index_build_parallelism()
        if parallelism <= 0:
            raise ValueError(
                "Option 'global-index.build.parallelism' must be greater than 0."
            )

        shards = _split_by_global_index_shard(
            splits, rows_per_shard, unindexed_ranges)
        if not shards:
            return []

        if parallelism == 1 or len(shards) == 1:
            messages = []
            try:
                for index_split, index_range in shards:
                    message = self._build_generic_shard(
                        index_split, index_range, index_field, table_read, index_path)
                    if message is not None:
                        messages.append(message)
                return messages
            except BaseException:
                self._delete_uncommitted_indexes(messages)
                raise

        # Workers record their own output so that rollback never depends on the
        # future list being fully built. ThreadPoolExecutor.submit() enqueues the
        # work item before it starts an extra worker, so a submission that raises
        # (RuntimeError: can't start new thread) may still run its shard on an
        # already running worker.
        completed = []
        completed_lock = threading.Lock()

        def build_shard(index_split, index_range):
            message = self._build_generic_shard(
                index_split, index_range, index_field, table_read, index_path)
            if message is not None:
                with completed_lock:
                    completed.append(message)
            return message

        futures = []
        try:
            with ThreadPoolExecutor(
                max_workers=min(parallelism, len(shards)),
                thread_name_prefix="paimon-global-index-build",
            ) as executor:
                try:
                    for index_split, index_range in shards:
                        futures.append(
                            executor.submit(build_shard, index_split, index_range))
                except BaseException:
                    # Keep queued shards that have not started from building an
                    # index file this build is about to delete.
                    for future in futures:
                        future.cancel()
                    raise
                done, _ = wait(futures, return_when=FIRST_EXCEPTION)
                failed = next(
                    (future for future in futures
                     if future in done and future.exception() is not None),
                    None,
                )
                if failed is not None:
                    for future in futures:
                        future.cancel()
                    failed.result()

                # Futures are consumed in shard-plan order so index manifest
                # messages are deterministic even when shards finish out of order.
                results = [future.result() for future in futures]
            return [message for message in results if message is not None]
        except BaseException:
            # Exiting the executor waits for in-flight shards to close their
            # readers and writers, so ``completed`` is stable and fully visible
            # here. Delete every index that was built because build() will not
            # return commit messages after a failure.
            self._delete_uncommitted_indexes(completed)
            raise

    def _build_generic_shard(
        self, index_split, index_range, index_field, table_read, index_path: str, file_name=None
    ) -> Optional[CommitMessage]:
        from pypaimon.read.read_support import _ClosableArrowBatchReader

        writer = None
        try:
            reader, batches = table_read._new_arrow_batch_reader([index_split])
            # Close the Python iterator explicitly on failure as well as
            # the Arrow reader, which may retain a suspended generator.
            with _ClosableArrowBatchReader(reader, batches) as batch_reader:
                for batch in batch_reader:
                    if batch.num_rows == 0:
                        continue
                    if writer is None:
                        writer = self._create_generic_index_writer(
                            index_path, index_field)
                        if file_name is not None:
                            writer.file_name = file_name
                    if self._index_type in VINDEX_IDENTIFIERS:
                        if batch.column(SpecialFields.ROW_ID.name).null_count:
                            raise ValueError(
                                "Cannot build global index because _ROW_ID is null.")
                        for offset in range(0, batch.num_rows, ADD_BATCH_SIZE):
                            _write_vector_batch(
                                writer, batch.slice(offset, ADD_BATCH_SIZE),
                                self._index_columns[0], index_range)
                    else:
                        for value, row_id in _extract_index_rows(
                            batch,
                            self._index_columns[0],
                            SpecialFields.ROW_ID.name,
                            index_range,
                        ):
                            writer.write(value, row_id - index_range.from_)
                    del batch

            if writer is None:
                return None

            index_adds = _to_index_manifest_entries(
                self._table,
                index_split.partition,
                index_range,
                index_field.id,
                self._index_type,
                writer.finish(),
            )
            if not index_adds:
                return None
            return CommitMessage(
                partition=tuple(index_split.partition.values),
                bucket=0,
                new_files=[],
                index_adds=index_adds,
            )
        except BaseException:
            if writer is not None:
                self._delete_writer_output(writer, index_path)
            raise
        finally:
            if writer is not None:
                writer.close()

    def _delete_writer_output(self, writer, index_path: str) -> None:
        file_name = getattr(writer, "file_name", None)
        if file_name:
            self._table.file_io.delete_quietly(
                "%s/%s" % (index_path.rstrip("/"), file_name))

    def _delete_uncommitted_indexes(self, messages) -> None:
        path_factory = self._table.path_factory().global_index_path_factory()
        for message in messages:
            for index_add in message.index_adds:
                index_file = index_add.index_file
                file_path = (
                    index_file.external_path
                    if index_file.external_path is not None
                    else path_factory.to_path(index_file.file_name)
                )
                self._table.file_io.delete_quietly(file_path)

    def _create_generic_index_writer(self, index_path: str, index_field):
        if self._index_type in VINDEX_IDENTIFIERS:
            return VindexVectorIndexWriter(
                self._table.file_io,
                index_path,
                index_field.type,
                self._index_type,
                self._options.to_map(),
                index_field.name,
                self._user_options,
            )
        if self._index_type == FULL_TEXT_IDENTIFIER:
            return NativeFullTextIndexWriter(
                self._table.file_io,
                index_path,
                index_field.type,
                self._options.to_map(),
            )
        raise ValueError("Unsupported generic global index type: %s" % self._index_type)


def _extract_sorted_rows(
    table: pa.Table,
    index_column: str,
    row_id_column: str,
    key_serializer,
    row_range: Optional[Range] = None,
):
    keys = table.column(index_column).to_pylist()
    row_ids = table.column(row_id_column).to_pylist()
    rows = []
    for key, row_id in zip(keys, row_ids):
        if row_id is None:
            raise ValueError("Cannot build global index because _ROW_ID is null.")
        row_id = int(row_id)
        if row_range is not None and not row_range.contains(row_id):
            continue
        rows.append((key, row_id))

    comparator = key_serializer.create_comparator()

    def compare(left, right):
        left_key = left[0]
        right_key = right[0]
        if left_key is None and right_key is None:
            return 0
        if left_key is None:
            return -1
        if right_key is None:
            return 1
        return comparator(left_key, right_key)

    return sorted(rows, key=cmp_to_key(compare))


def _write_vector_batch(writer, batch, index_column, row_range):
    row_ids = batch.column(SpecialFields.ROW_ID.name)
    if row_ids.null_count:
        raise ValueError("Cannot build global index because _ROW_ID is null.")
    vectors = batch.column(index_column)
    selected = pc.and_(
        pc.greater_equal(row_ids, row_range.from_),
        pc.less_equal(row_ids, row_range.to),
    )
    if not pc.all(selected).as_py():
        row_ids = pc.filter(row_ids, selected)
        vectors = pc.filter(vectors, selected)
    writer.write_batch(vectors, pc.subtract(row_ids, row_range.from_))


def _extract_index_rows(
    table: Union[pa.Table, pa.RecordBatch],
    index_column: str,
    row_id_column: str,
    row_range: Optional[Range] = None,
):
    values = table.column(index_column).to_pylist()
    row_ids = table.column(row_id_column).to_pylist()
    rows = []
    for value, row_id in zip(values, row_ids):
        if row_id is None:
            raise ValueError("Cannot build global index because _ROW_ID is null.")
        row_id = int(row_id)
        if row_range is not None and not row_range.contains(row_id):
            continue
        rows.append((value, row_id))
    return rows


def _chunks(rows, size):
    for start in range(0, len(rows), size):
        yield rows[start:start + size]


def _to_index_manifest_entries(
    table,
    partition: GenericRow,
    row_range: Range,
    index_field_id: int,
    index_type: str,
    result_entries,
    source_meta=None,
) -> List[IndexManifestEntry]:
    path_factory = table.path_factory().global_index_path_factory()
    entries = []
    for result in result_entries:
        file_path = path_factory.to_path(result.file_name)
        file_size = table.file_io.get_file_size(file_path)
        external_path = file_path if path_factory.is_external_path() else None
        index_file = IndexFileMeta(
            index_type=index_type,
            file_name=result.file_name,
            file_size=file_size,
            row_count=result.row_count,
            global_index_meta=GlobalIndexMeta(
                row_range_start=row_range.from_,
                row_range_end=row_range.to,
                index_field_id=index_field_id,
                extra_field_ids=None,
                index_meta=result.meta,
                source_meta=source_meta,
            ),
            external_path=external_path,
        )
        entries.append(
            IndexManifestEntry(
                kind=0,
                partition=partition,
                bucket=0,
                index_file=index_file,
            )
        )
    return entries
