# 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 hashing and routing for distributed bucket execution."""

import math
import struct
from typing import Any, Dict, List, Tuple

import pyarrow as pa

from pypaimon.common.options.core_options import CoreOptions
from pypaimon.execution.python.write.dynamic_bucket import DynamicBucketAssigner, compute_assigner
from pypaimon.index.dynamic_bucket import resolve_bucket_snapshot, to_signed_int32
from pypaimon.schema.data_types import AtomicType
from pypaimon.schema.table_schema import TableSchema
from pypaimon.table.bucket_mode import BucketMode
from pypaimon.table.row.generic_row import GenericRow, GenericRowSerializer
from pypaimon.table.row.internal_row import RowKind


_MURMUR_C1 = 0xCC9E2D51
_MURMUR_C2 = 0x1B873593
_DEFAULT_SEED = 42


def _mix_k1(k1: int) -> int:
    k1 = (k1 * _MURMUR_C1) & 0xFFFFFFFF
    k1 = ((k1 << 15) | (k1 >> 17)) & 0xFFFFFFFF
    k1 = (k1 * _MURMUR_C2) & 0xFFFFFFFF
    return k1


def _mix_h1(h1: int, k1: int) -> int:
    h1 = (h1 ^ k1) & 0xFFFFFFFF
    h1 = ((h1 << 13) | (h1 >> 19)) & 0xFFFFFFFF
    h1 = (h1 * 5 + 0xE6546B64) & 0xFFFFFFFF
    return h1


def _fmix(h1: int, length: int) -> int:
    h1 = (h1 ^ length) & 0xFFFFFFFF
    h1 ^= h1 >> 16
    h1 = (h1 * 0x85EBCA6B) & 0xFFFFFFFF
    h1 ^= h1 >> 13
    h1 = (h1 * 0xC2B2AE35) & 0xFFFFFFFF
    h1 ^= h1 >> 16
    return h1


def _hash_bytes_by_words(data: bytes, seed: int = _DEFAULT_SEED) -> int:
    n = len(data)
    length_aligned = n - (n % 4)
    h1 = seed
    for i in range(0, length_aligned, 4):
        k1 = struct.unpack_from("<I", data, i)[0]
        k1 = _mix_k1(k1)
        h1 = _mix_h1(h1, k1)
    return _fmix(h1, n)


def _bucket_from_hash(hash_unsigned: int, num_buckets: int) -> int:
    if hash_unsigned >= 0x80000000:
        hash_signed = hash_unsigned - 0x100000000
    else:
        hash_signed = hash_unsigned
    rem = hash_signed - math.trunc(hash_signed / num_buckets) * num_buckets
    return abs(rem)


class PartitionKeyExtractor:
    """Resolve input routing fields and hash their Java binary layout."""

    def __init__(self, table_schema: TableSchema):
        self.table_schema = table_schema
        self.partition_indices = self._get_field_indices(table_schema.partition_keys)

    def extract_partition_bucket_batch(self, data: pa.RecordBatch) -> Tuple[List[Tuple], List[int]]:
        return self._extract_partitions_batch(data), self._extract_buckets_batch(data)

    def extract_partition_bucket_row(
            self, values_by_name: Dict[str, Any]) -> Tuple[Tuple, int]:
        partition = tuple(
            values_by_name[self.table_schema.fields[i].name]
            for i in self.partition_indices
        )
        bucket = self._extract_bucket_row(values_by_name)
        return partition, bucket

    def _get_field_indices(self, field_names: List[str]) -> List[int]:
        if not field_names:
            return []
        field_map = {field.name: i for i, field in enumerate(self.table_schema.fields)}
        return [field_map[name] for name in field_names if name in field_map]

    def _extract_partitions_batch(self, data: pa.RecordBatch) -> List[Tuple]:
        if not self.partition_indices:
            return [() for _ in range(data.num_rows)]

        partition_columns = self._input_columns(data, self.partition_indices)

        partitions = []
        for row_idx in range(data.num_rows):
            partition_values = tuple(col[row_idx].as_py() for col in partition_columns)
            partitions.append(partition_values)

        return partitions

    def _input_columns(self, data: pa.RecordBatch, field_indices: List[int]):
        """Resolve routing fields in the actual write type, as Java's converter does."""
        columns = []
        for field_index in field_indices:
            name = self.table_schema.fields[field_index].name
            index = data.schema.get_field_index(name)
            if index < 0:
                raise ValueError(f"Input must contain exactly one routing column '{name}'.")
            columns.append(data.column(index))
        return columns

    @staticmethod
    def _binary_row_hash_code(values: Tuple, fields: List) -> int:
        return _hash_bytes_by_words(
            GenericRowSerializer.to_bytes(
                GenericRow(list(values), fields, RowKind.INSERT)
            )[4:]
        )


class PostponeFixedBucketInputRouter(PartitionKeyExtractor):
    """Group distributed inputs by the same partition and bucket as writers."""

    def __init__(self, table, bucket_plan):
        super().__init__(table.table_schema)
        if table.options.bucket() != BucketMode.POSTPONE_BUCKET.value:
            raise ValueError(
                "Postpone fixed bucket writes require bucket = -2, got {}".format(
                    table.options.bucket()
                )
            )
        bucket_function = str(
            table.table_schema.options.get("bucket-function.type", "default")
        ).strip().lower()
        if bucket_function != "default":
            raise ValueError(
                "Postpone fixed bucket writes only support "
                "bucket-function.type=default, got {}"
                .format(bucket_function)
            )
        self.bucket_keys = table.table_schema.bucket_keys
        self.bucket_key_indices = self._get_field_indices(self.bucket_keys)
        self._bucket_key_fields = table.table_schema.logical_bucket_key_fields
        self._bucket_plan = bucket_plan

    def with_bucket_plan(self, bucket_plan) -> None:
        self._bucket_plan = bucket_plan

    def num_buckets(self, partition: Tuple) -> int:
        return self._bucket_plan.num_buckets(partition)

    def route(self, data) -> pa.Int32Array:
        """Return bucket IDs in input order, as the Native router does."""
        return pa.array(self.extract_partition_bucket_batch(data)[1], type=pa.int32())

    def extract_partition_bucket_batch(
        self, data: pa.RecordBatch
    ) -> Tuple[List[Tuple], List[int]]:
        partitions = self._extract_partitions_batch(data)
        columns = self._input_columns(data, self.bucket_key_indices)
        buckets = [
            _bucket_from_hash(
                self._binary_row_hash_code(
                    tuple(col[row_idx].as_py() for col in columns),
                    self._bucket_key_fields,
                ),
                self.num_buckets(partition),
            )
            for row_idx, partition in enumerate(partitions)
        ]
        return partitions, buckets

    def _extract_buckets_batch(self, data: pa.RecordBatch) -> List[int]:
        return self.extract_partition_bucket_batch(data)[1]

    def _extract_bucket_row(self, values_by_name: Dict[str, Any]) -> int:
        partition = tuple(
            values_by_name[self.table_schema.fields[i].name]
            for i in self.partition_indices
        )
        return _bucket_from_hash(
            self._binary_row_hash_code(
                tuple(values_by_name[name] for name in self.bucket_keys),
                self._bucket_key_fields,
            ),
            self.num_buckets(partition),
        )


class FixedBucketInputRouter(PartitionKeyExtractor):
    """Route distributed inputs without constructing a Python file writer."""

    def __init__(self, table_schema: TableSchema):
        super().__init__(table_schema)
        options = CoreOptions.from_dict(table_schema.options)
        self.num_buckets = options.bucket()
        if self.num_buckets <= 0:
            raise ValueError(f"Fixed bucket mode requires bucket > 0, got {self.num_buckets}")

        # Bucket-key resolution lives on TableSchema (mirrors Java
        # ``TableSchema.bucketKeys()`` / ``logicalBucketKeyType()``); reuse
        # it so any reader path that walks the same logic stays in sync.
        self.bucket_keys = table_schema.bucket_keys
        self.bucket_key_indices = self._get_field_indices(self.bucket_keys)
        self._bucket_key_fields = table_schema.logical_bucket_key_fields
        bucket_function = table_schema.options.get('bucket-function.type')
        self.bucket_function = 'default' if bucket_function is None else str(bucket_function).lower()
        if self.bucket_function == 'mod':
            if len(self._bucket_key_fields) != 1:
                raise ValueError('bucket key must have exactly one field in mod bucket function')
            key_type = self._bucket_key_fields[0].type
            if not isinstance(key_type, AtomicType) or key_type.type.upper() not in ('INT', 'INTEGER', 'BIGINT'):
                raise ValueError(
                    'bucket key type must be INT or BIGINT in mod bucket function, but got %s' % key_type)
        elif self.bucket_function not in ('default', 'hive'):
            raise ValueError('Unsupported bucket function type: %s' % self.bucket_function)

    def route(self, data) -> pa.Int32Array:
        """Return bucket IDs in input order, as the Native router does."""
        return pa.array(self.extract_partition_bucket_batch(data)[1], type=pa.int32())

    def _extract_buckets_batch(self, data: pa.RecordBatch) -> List[int]:
        self._check_automatic_bucket_function()
        columns = self._input_columns(data, self.bucket_key_indices)
        if self.bucket_function == 'mod':
            return [self._mod_bucket(value.as_py()) for value in columns[0]]
        return [
            _bucket_from_hash(
                self._binary_row_hash_code(
                    tuple(col[row_idx].as_py() for col in columns),
                    self._bucket_key_fields,
                ),
                self.num_buckets,
            )
            for row_idx in range(data.num_rows)
        ]

    def _extract_bucket_row(self, values_by_name: Dict[str, Any]) -> int:
        self._check_automatic_bucket_function()
        if self.bucket_function == 'mod':
            return self._mod_bucket(values_by_name[self.bucket_keys[0]])
        return _bucket_from_hash(
            self._binary_row_hash_code(
                tuple(values_by_name[name] for name in self.bucket_keys),
                self._bucket_key_fields,
            ),
            self.num_buckets,
        )

    def _check_automatic_bucket_function(self):
        # Explicit buckets do not use this method. A single bucket also keeps
        # the existing zero result without needing the Hive hash algorithm.
        if self.bucket_function == 'hive' and self.num_buckets > 1:
            raise NotImplementedError(
                'Hive bucket functions require the native writer; enable write.native.enabled')

    def _mod_bucket(self, value):
        # Java reads the zeroed fixed-width slot for NULL; Python's modulo
        # with a positive divisor otherwise matches Math.floorMod, even for
        # Long.MIN_VALUE. Avoid floating-point division for BIGINT values.
        return 0 if value is None else value % self.num_buckets


class DynamicBucketInputRouter(PartitionKeyExtractor):
    """Hash dynamic-bucket input without assigning buckets or maintaining indexes."""

    def __init__(self, table_schema: TableSchema):
        super().__init__(table_schema)
        num_buckets = int(table_schema.options.get(CoreOptions.BUCKET.key(), -1))
        if num_buckets != -1:
            raise ValueError(
                "Only 'bucket' = '-1' is allowed for "
                f"'DynamicBucketRowKeyExtractor', but found: {num_buckets}"
            )
        if table_schema.options.get(CoreOptions.BUCKET_KEY.key()) is not None:
            raise ValueError("Cannot define 'bucket-key' in dynamic bucket mode")
        self.bucket_keys = table_schema.bucket_keys
        self.bucket_key_indices = self._get_field_indices(self.bucket_keys)
        self._bucket_key_fields = table_schema.logical_bucket_key_fields
        self._partition_fields = [
            table_schema.fields[index] for index in self.partition_indices
        ]

    def extract_hashes_batch(
        self, data: pa.RecordBatch
    ) -> Tuple[List[Tuple], List[int], List[int]]:
        """Return partitions, BinaryRow partition hashes, and key hashes."""
        partitions, partition_hashes = self.extract_partition_hashes_batch(data)
        return partitions, partition_hashes, self._extract_key_hashes_batch(data)

    def extract_partition_hashes_batch(self, data: pa.RecordBatch) -> Tuple[List[Tuple], List[int]]:
        """Hash partitions independently when key hashes arrived from upstream."""
        partitions = self._extract_partitions_batch(data)
        partition_hash_cache = {}
        partition_hashes = []
        for partition in partitions:
            if partition not in partition_hash_cache:
                partition_hash_cache[partition] = self._binary_row_hash_code(
                    partition, self._partition_fields
                )
            partition_hashes.append(partition_hash_cache[partition])
        return partitions, partition_hashes

    def _extract_key_hashes_batch(self, data: pa.RecordBatch) -> List[int]:
        key_columns = self._input_columns(data, self.bucket_key_indices)
        return [
            self._binary_row_hash_code(
                tuple(column[row_idx].as_py() for column in key_columns),
                self._bucket_key_fields,
            )
            for row_idx in range(data.num_rows)
        ]

    def extract_assigners_batch(
        self, data: pa.RecordBatch, num_channels: int, num_assigners: int
    ) -> List[int]:
        _, partition_hashes, key_hashes = self.extract_hashes_batch(data)
        return [
            compute_assigner(
                partition_hash, key_hash, num_channels, num_assigners
            )
            for partition_hash, key_hash in zip(partition_hashes, key_hashes)
        ]


class PythonDynamicBucketAssignerRouter:
    """Route input rows to dynamic bucket assigners and carry their key hashes."""

    def __init__(self, table, num_channels, num_assigners):
        if num_channels <= 0 or num_assigners <= 0:
            raise ValueError('num_channels and num_assigners must be positive')
        self._router = DynamicBucketInputRouter(table.table_schema)
        self._num_channels = num_channels
        self._num_assigners = num_assigners

    def route(self, data) -> pa.RecordBatch:
        _, partition_hashes, key_hashes = self._router.extract_hashes_batch(data)
        return pa.RecordBatch.from_arrays([
            pa.array([compute_assigner(partition_hash, key_hash, self._num_channels, self._num_assigners)
                      for partition_hash, key_hash in zip(partition_hashes, key_hashes)], type=pa.int32()),
            pa.array([to_signed_int32(key_hash) for key_hash in key_hashes], type=pa.int32()),
        ], names=['assigner', 'key_hash'])


class PythonDynamicBucketAssigner:

    def __init__(self, table, num_channels, num_assigners, assign_id,
                 ignore_existing=False, base_snapshot_id=None):
        self._router = DynamicBucketInputRouter(table.table_schema)
        snapshot = None if ignore_existing else resolve_bucket_snapshot(table, base_snapshot_id)
        self.restore_snapshot_id = snapshot.id if snapshot is not None else 0
        self._assigner = DynamicBucketAssigner(
            table, num_channels=num_channels, num_assigners=num_assigners, assign_id=assign_id,
            target_bucket_row_number=table.options.dynamic_bucket_target_row_num(),
            max_buckets_num=table.options.dynamic_bucket_max_buckets(),
            ignore_existing=ignore_existing, snapshot=snapshot)

    def assign(self, data, key_hashes=None) -> pa.Int32Array:
        if key_hashes is None:
            partitions, partition_hashes, hashes = self._router.extract_hashes_batch(data)
        else:
            if isinstance(key_hashes, pa.ChunkedArray):
                key_hashes = key_hashes.combine_chunks()
            if not isinstance(key_hashes, pa.Int32Array):
                raise TypeError('Dynamic bucket key hashes must be an Int32Array')
            if len(key_hashes) != data.num_rows or key_hashes.null_count:
                raise ValueError('Dynamic bucket key hashes must be non-null and match the input row count')
            partitions, partition_hashes = self._router.extract_partition_hashes_batch(data)
            hashes = key_hashes.to_pylist()
        return pa.array([bucket for bucket, _ in self._assigner.assign_batch(
            partitions, partition_hashes, hashes)], type=pa.int32())
