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

from typing import Any, Dict, List, Sequence, Union

import pyarrow as pa

from pypaimon.schema.data_types import PyarrowFieldParser, is_blob_file_field
from pypaimon.table.special_fields import SpecialFields
from pypaimon.write.commit_message import CommitMessage
from pypaimon.write.row_utils import (inline_blob_value, require_columns, row_to_named_values, value_for_arrow)


RowIdInput = Union[Sequence[int], pa.Array, pa.ChunkedArray]


def normalize_row_ids(row_ids: RowIdInput):
    """Validate IDs without turning Arrow buffers into Python objects.

    Keep chunk boundaries for Native transport. Only integer Arrow layouts
    have a row-ID identity; floating, Boolean and untyped NULL arrays must not
    be silently converted. Existing sequence callers retain integer coercion.
    """
    if isinstance(row_ids, (pa.Array, pa.ChunkedArray)):
        if not pa.types.is_integer(row_ids.type):
            raise TypeError('_ROW_ID input must be an integer Arrow array')
        if row_ids.null_count:
            raise ValueError('_ROW_ID value must not be null.')
        return row_ids.cast(pa.int64(), safe=True)
    values = []
    for row_id in row_ids:
        if row_id is None:
            raise ValueError('_ROW_ID value must not be null.')
        values.append(int(row_id))
    return values


class RowIdUpdateInputMixin:
    """Normalize Python row inputs for either update execution backend."""

    def update_row_columns(
            self,
            row,
            row_ids: List[int],
            column_names: List[str],
    ) -> List[CommitMessage]:
        return self.update_rows_columns([row], [row_ids], column_names)

    def update_rows_columns(
            self,
            rows: List,
            row_ids_by_row: List[List[int]],
            column_names: List[str],
    ) -> List[CommitMessage]:
        if not column_names:
            raise ValueError("column_names cannot be empty")
        column_names = list(dict.fromkeys(column_names))
        if len(rows) != len(row_ids_by_row):
            raise ValueError(
                "rows and row_ids_by_row must have the same length: "
                f"{len(rows)} != {len(row_ids_by_row)}"
            )

        values_by_row = [
            row_to_named_values(row, self.table.table_schema.fields)
            for row in rows
        ]
        for values_by_name in values_by_row:
            require_columns(values_by_name, column_names, "update_rows_columns")

        row_entries = []
        for values_by_name, row_ids in zip(values_by_row, row_ids_by_row):
            row_entries.extend((row_id, values_by_name) for row_id in row_ids)

        if not row_entries:
            return []

        row_entries.sort(key=lambda item: item[0])

        for col_name in column_names:
            if col_name not in self.table.field_names:
                raise ValueError(f"Column {col_name} not found in table schema")

        arrays = [
            pa.array([row_id for row_id, _ in row_entries], type=pa.int64())
        ]
        fields = [pa.field(SpecialFields.ROW_ID.name, pa.int64())]
        blob_object_columns: Dict[str, List[Any]] = {}
        descriptor_fields = self.table.options.blob_descriptor_fields()
        view_fields = self.table.options.blob_view_fields()

        for col_name in column_names:
            if self._is_blob_column(col_name):
                blob_object_columns[col_name] = [
                    values_by_name[col_name]
                    for _, values_by_name in row_entries
                ]
                continue

            table_field = self.table.field_dict[col_name]
            arrow_field = PyarrowFieldParser.from_paimon_field(table_field)
            arrays.append(
                pa.array(
                    [
                        value_for_arrow(inline_blob_value(
                            values_by_name[col_name],
                            col_name in descriptor_fields, col_name in view_fields), table_field)
                        for _, values_by_name in row_entries
                    ],
                    type=arrow_field.type,
                )
            )
            fields.append(arrow_field)

        update_data = pa.Table.from_arrays(arrays, schema=pa.schema(fields))
        return self._write_row_columns(update_data, column_names, blob_object_columns)

    def _is_blob_column(self, column_name: str) -> bool:
        if column_name in (self.table.options.blob_descriptor_fields() | self.table.options.blob_view_fields()):
            return False
        for table_field in self.table.fields:
            if table_field.name == column_name:
                return is_blob_file_field(table_field)
        return False
