# 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 grouping for distributed row-ID plans, selected before execution."""

import pyarrow as pa

from pypaimon.manifest.schema.data_file_meta import DataFileMeta
from pypaimon.read.query_auth_split import QueryAuthSplit
from pypaimon.utils.data_evolution_utils import retrieve_anchor_file
from pypaimon.utils.range import Range
from pypaimon.utils.range_helper import RangeHelper


def _file_groups(split):
    if isinstance(split, QueryAuthSplit):
        for group in _file_groups(split.split):
            yield QueryAuthSplit(group, split.auth_result)
    else:
        normal, dedicated = [], []
        names = set()
        for file in split.files:
            file.non_null_row_id_range()
            if file.file_name in names:
                raise ValueError('A row-ID split contains duplicate file metadata')
            names.add(file.file_name)
            if DataFileMeta.is_blob_file(file.file_name) or DataFileMeta.is_vector_file(file.file_name):
                dedicated.append(file)
            else:
                normal.append(file)
        if not normal:
            raise ValueError('A row-ID split requires a normal anchor file')
        if split.data_deletion_files is not None and len(split.data_deletion_files) != len(split.files):
            raise ValueError('Row-ID deletion metadata must match the captured data files')
        matched = set()
        for files in RangeHelper(lambda file: file.non_null_row_id_range()).merge_overlapping_ranges(normal):
            anchor_range = retrieve_anchor_file(files).non_null_row_id_range()
            if any(file.non_null_row_id_range() != anchor_range for file in files):
                raise ValueError('Overlapping row-ID anchors must have identical ranges')
            files += [file for file in dedicated if anchor_range.overlaps(file.non_null_row_id_range())]
            selected_names = {file.file_name for file in files}
            matched.update(selected_names)
            # Keep the captured physical paths and aligned deletion metadata.
            # Dedicated files may serve more than one normal anchor, but never
            # merge those owners or make the gaps between them addressable.
            group = split.filter_file(lambda file: file.file_name in selected_names)
            group.raw_convertible = len(group.files) == 1
            yield group
        if matched != names:
            raise ValueError('A row-ID split contains a dedicated file without its normal anchor')


def row_id_groups(plan):
    groups = []
    for planned in plan.splits():
        for split in _file_groups(planned):
            anchor_range = retrieve_anchor_file(split.files).non_null_row_id_range()
            groups.append((anchor_range.from_, anchor_range.to, split))
    return sorted(groups, key=lambda group: group[0])


def validate_live_row_ids(table, info, first_row_id, row_ids):
    """Reject deleted updates using only the routed snapshot's DV files.

    The writer must still merge physical rows, including tombstones, to preserve
    row-id offsets. Filtering the writer's original data would shift those offsets.
    """
    from pypaimon.execution.python.deletionvectors.deletion_vector import DeletionVector

    split, files = info.first_row_id_index[first_row_id]
    if split.data_deletion_files is None:
        return
    row_ids = row_ids.to_pylist()
    target_names = {file.file_name for file in files}
    for file, deletion in zip(split.files, split.data_deletion_files):
        if deletion is None or file.file_name not in target_names:
            continue
        vector = DeletionVector.read(table.file_io, deletion)
        for row_id in row_ids:
            if file.row_id_range().contains(row_id) and vector.is_deleted(row_id - file.first_row_id):
                raise ValueError("Cannot update deleted _ROW_ID {}.".format(row_id))


class PythonRowIdPlan:
    """Route captured metadata with no file access or mutation state."""

    def __init__(self, plan, groups=None):
        import numpy as np
        from pypaimon.table.row.generic_row import GenericRowSerializer

        self.plan = plan
        self.groups = row_id_groups(plan) if groups is None else groups
        self._starts = np.asarray([first for first, _, _ in self.groups], dtype=np.int64)
        self._ends = np.asarray([last for _, last, _ in self.groups], dtype=np.int64)
        if any(left[1] >= right[0] for left, right in zip(self.groups, self.groups[1:])):
            raise ValueError('A row-ID plan contains overlapping file groups')
        owners = {}
        bucket_owners = []
        for first, _, split in self.groups:
            identity = (GenericRowSerializer.to_bytes(split.partition), split.bucket)
            bucket_owners.append(owners.setdefault(identity, first))
        self._bucket_owners = np.asarray(bucket_owners, dtype=np.int64)

    def _positions(self, row_ids):
        import numpy as np

        values = row_ids.to_numpy(zero_copy_only=False)
        positions = np.searchsorted(self._starts, values, side='right') - 1
        if len(values) == 0:
            return positions
        if not self.groups:
            valid = np.zeros(len(values), dtype=bool)
        else:
            valid = (values >= 0) & (positions >= 0) & (values <= self._ends[np.maximum(positions, 0)])
        if not valid.all():
            bad = values[~valid][0]
            ranges = ['[{}, {}]'.format(first, last) for first, last, _ in self.groups]
            raise ValueError('_ROW_ID {} does not belong to any valid range {}; planner snapshot is stale '
                             'or matched rows come from a different table.'.format(bad, ranges))
        return positions

    def route(self, row_ids):
        return pa.array(self._starts[self._positions(row_ids)], type=pa.int64())

    def route_by_bucket(self, row_ids):
        return pa.array(self._bucket_owners[self._positions(row_ids)], type=pa.int64())

    def select(self, row_ids):
        from pypaimon.globalindex.indexed_split import IndexedSplit

        positions = self._positions(row_ids)
        requested = {}
        for position, row_id in zip(positions, row_ids.to_pylist()):
            requested.setdefault(int(position), set()).add(row_id)
        splits = []
        for position in sorted(requested):
            split = self.groups[position][2]
            ranges = Range.to_ranges(list(requested[position]))
            if isinstance(split, QueryAuthSplit):
                splits.append(QueryAuthSplit(IndexedSplit(split.split, ranges), split.auth_result))
            else:
                splits.append(IndexedSplit(split, ranges))
        return self.plan._with_splits(splits)

    def for_plan(self, plan, groups):
        return PythonRowIdPlan(plan, groups)
