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

"""Freshness checks for global indexes on data-evolution tables."""

import logging

from pypaimon.common.options.core_options import CoreOptions, GlobalIndexColumnUpdateAction
from pypaimon.table.special_fields import SpecialFields

logger = logging.getLogger(__name__)


def key_indexes_are_fresh(table, snapshot, match_keys, partition_predicate):
    """Check whether IGNORE may have left indexed match keys stale."""
    if table.options.global_index_column_update_action() != GlobalIndexColumnUpdateAction.IGNORE:
        return True
    if snapshot is None or not match_keys:
        return True
    from pypaimon.execution.python.globalindex.data_evolution_global_index_scanner import (
        is_supported_scalar_index,
    )
    from pypaimon.index.data_evolution_index_source_meta import DataEvolutionIndexSourceMeta
    from pypaimon.index.index_file_handler import IndexFileHandler
    from pypaimon.read.push_down_utils import trim_and_transform_predicate

    try:
        key_ids = {table.field_dict[key].id for key in match_keys}
        partition_filter = trim_and_transform_predicate(
            partition_predicate, table.field_names, table.partition_keys)
        native_planning = table.options.native_read_enabled() or table.options.native_plan_enabled()

        def relevant_index(entry):
            meta = entry.index_file.global_index_meta
            # Native planning can use more index types, including composite
            # BTree, even when Python performs the final key matching.
            supported = (is_supported_scalar_index(entry.index_file)
                         or (native_planning and meta is not None
                             and entry.index_file.index_type.lower() in ('btree', 'bitmap', 'fm', 'multivalue')))
            return (supported
                    and bool(key_ids.intersection(
                        [meta.index_field_id] + (meta.extra_field_ids or [])))
                    and (partition_filter is None or partition_filter.test(entry.partition)))

        indexes = IndexFileHandler(table).scan(snapshot, relevant_index)
        if not indexes:
            return True
        baselines = []
        for index in indexes:
            meta = index.index_file.global_index_meta
            source = DataEvolutionIndexSourceMeta.deserialize(meta.source_meta)
            if source.scan_snapshot_id > snapshot.id or meta.row_range_start > meta.row_range_end:
                return False
            baselines.append((index, source.scan_snapshot_id))

        # Inspect active file metadata before either key stats or an index can
        # hide the files containing changed keys. Both plans use this snapshot.
        builder = table.copy_without_time_travel({
            CoreOptions.GLOBAL_INDEX_ENABLED.key(): 'false',
        }).new_read_builder().with_filter(partition_predicate)
        indexed_groups = {(tuple(index.partition.values), index.bucket) for index, _ in baselines}
        files_by_group = {}
        for split in builder.new_scan().plan_all().splits():
            group = (tuple(split.partition.values), split.bucket)
            if group in indexed_groups:
                files = files_by_group.setdefault(group, {})
                files.update((file.file_name, file) for file in split.files)
        ranges_by_group = {}
        for group, files in files_by_group.items():
            ranges = []
            for file in files.values():
                row_range = file.row_id_range()
                if row_range is None:
                    return False
                ranges.append((row_range.from_, row_range.to, file))
            ranges_by_group[group] = _FileRangeIndex(ranges)

        schema = table.table_schema
        known_names = set(table.field_names) | SpecialFields.SYSTEM_FIELD_NAMES
        for index, baseline in baselines:
            meta = index.index_file.global_index_meta
            indexed_keys = key_ids.intersection([meta.index_field_id] + (meta.extra_field_ids or []))
            ranges = ranges_by_group.get((tuple(index.partition.values), index.bucket))
            if ranges is None:
                continue
            for file in ranges.overlapping(meta.row_range_start, meta.row_range_end):
                # Historical schemas are outside this optimization's proof.
                if file.schema_id != schema.id:
                    return False
                if file.write_cols is not None and (
                        any(name not in known_names for name in file.write_cols)
                        or len(file.write_cols) != len(set(file.write_cols))):
                    return False
                fields = schema.data_file_fields(file.write_cols)
                sequences = file.write_cols_sequences
                for position, field in enumerate(fields):
                    if field.id not in indexed_keys:
                        continue
                    sequence = (sequences[position]
                                if sequences is not None and len(sequences) == len(fields)
                                else file.max_sequence_number)
                    if sequence <= 0 or sequence > file.max_sequence_number or sequence > baseline:
                        return False
        return True
    except Exception:
        logger.debug("Cannot verify upsert key index freshness; scanning without indexes.", exc_info=True)
        return False


class _FileRangeIndex:
    """Centered interval tree for inclusive physical-file row ranges.

    Build once per partition/bucket in O(F log F); each shard visits only
    O(log F + overlapping files), including nested and long column files.
    """

    def __init__(self, ranges):
        self._root = self._build(sorted(ranges, key=lambda item: item[0]))

    @classmethod
    def _build(cls, ranges):
        if not ranges:
            return None
        center = ranges[len(ranges) // 2][0]
        left, crossing, right = [], [], []
        for item in ranges:
            start, end, _ = item
            if end < center:
                left.append(item)
            elif start > center:
                right.append(item)
            else:
                crossing.append(item)
        # Filtering preserves start order; each file belongs to one node only.
        by_end = sorted(crossing, key=lambda item: item[1], reverse=True)
        return center, crossing, by_end, cls._build(left), cls._build(right)

    def overlapping(self, start, end):
        pending = [self._root]
        while pending:
            node = pending.pop()
            if node is None:
                continue
            center, by_start, by_end, left, right = node
            if end < center:
                for file_start, _, file in by_start:
                    if file_start > end:
                        break
                    yield file
                pending.append(left)
            elif start > center:
                for _, file_end, file in by_end:
                    if file_end < start:
                        break
                    yield file
                pending.append(right)
            else:
                for _, _, file in by_start:
                    yield file
                pending.extend((left, right))
