# 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 TYPE_CHECKING, Any, Dict, List, Optional

import pyarrow as pa

from pypaimon.common.options.core_options import ChangelogProducer
from pypaimon.schema.arrow_schema import arrow_schemas_compatible, normalize_arrow_strings
from pypaimon.schema.data_types import PyarrowFieldParser
from pypaimon.snapshot.snapshot import BATCH_COMMIT_IDENTIFIER
from pypaimon.table.row.blob import BlobConsumer
from pypaimon.write.row_utils import (
    require_columns,
    row_to_named_values,
)
from pypaimon.write.commit_message import CommitMessage
from pypaimon.write.file_store_write import FileStoreWrite

if TYPE_CHECKING:
    from ray.data import Dataset


class TableWrite:
    def __init__(self, table, commit_user, static_partition: Optional[dict] = None,
                 *, restore_snapshot_id=None):
        from pypaimon.table.file_store_table import FileStoreTable

        self.table: FileStoreTable = table
        self.table_pyarrow_schema = PyarrowFieldParser.from_paimon_schema(self.table.table_schema.fields)
        self.commit_user = commit_user
        self.static_partition = static_partition
        self.restore_snapshot_id = restore_snapshot_id
        self.file_store_write = self._create_file_store_write(commit_user)
        self.file_store_write.restore_snapshot_id = (
            0 if static_partition is not None and restore_snapshot_id is not None
            else restore_snapshot_id)
        if static_partition is not None:
            # An overwrite replaces state, not an input changelog. Java's
            # overwrite commit does not publish changelog manifests; avoid
            # writing unreferenced changelog files in the first place.
            self.file_store_write.changelog_producer = ChangelogProducer.NONE
        self.row_key_extractor = self._create_row_key_extractor(static_partition)

    def _create_file_store_write(self, commit_user):
        return FileStoreWrite(self.table, commit_user)

    def _create_row_key_extractor(self, static_partition):
        if self.restore_snapshot_id is not None:
            from pypaimon.write.row_key_extractor import DynamicBucketRowKeyExtractor
            return DynamicBucketRowKeyExtractor(
                self.table.table_schema, table=self.table,
                ignore_existing=static_partition is not None,
                base_snapshot_id=self.restore_snapshot_id)
        return self.table.create_row_key_extractor(
            ignore_existing=static_partition is not None
        )

    def write_arrow(self, data, bucket: Optional[int] = None):
        """Write Arrow data, optionally to a bucket assigned upstream."""
        self._validate_pyarrow_schema(data.schema)
        if isinstance(data, pa.RecordBatch):
            return self.write_arrow_batch(data, bucket)
        for batch in data.to_batches():
            self.write_arrow_batch(batch, bucket)

    def write_arrow_batch(self, data: pa.RecordBatch, bucket: Optional[int] = None):
        if bucket is not None:
            return self._write_precomputed_bucket(data, bucket)
        data = self._prepare_arrow_data(data)

        for partition, bucket, row_indices in \
                self.row_key_extractor.extract_partition_bucket_groups(data):
            if row_indices is None:
                # Every input row belongs to the same partition/bucket. Passing the
                # original batch through avoids copying large BLOB values through
                # Arrow take before the dedicated BLOB writer consumes them.
                sub_table = data
            else:
                # row_indices is an int64 array of this group's rows in
                # ascending input order (the extractor sorts grouped indices so
                # sequence-number assignment stays latest-wins correct), so the
                # span is just first..last.
                lo = row_indices[0].as_py()
                hi = row_indices[-1].as_py()
                count = len(row_indices)
                if hi - lo + 1 == count:
                    # Distinct row indices spanning exactly `count` values are
                    # contiguous, so share the original Arrow buffers instead of
                    # gathering their rows into newly allocated buffers with take.
                    sub_table = data.slice(lo, count)
                else:
                    sub_table = pa.compute.take(data, row_indices)
            self._write_partition_bucket_batch(partition, bucket, sub_table)

    def roll_before_group_if_needed(self, row_count: int):
        """Roll current files before the next logical write group if needed."""
        if isinstance(row_count, bool) or not isinstance(row_count, int) \
                or row_count <= 0:
            raise ValueError("Group row count must be a positive integer.")
        self.file_store_write.roll_before_group_if_needed(row_count)

    def _write_partition_bucket_batch(self, partition, bucket, data):
        self.file_store_write.write(partition, bucket, data)

    def _write_precomputed_bucket(self, data, bucket):
        """Write one partition/bucket group using normal index maintenance."""
        from pypaimon.table.bucket_mode import BucketMode
        from pypaimon.write.row_key_extractor import DynamicBucketRowKeyExtractor

        bucket_mode = self.table.bucket_mode()
        if bucket_mode not in (BucketMode.HASH_FIXED, BucketMode.HASH_DYNAMIC):
            raise ValueError(
                "Precomputed bucket writes are only valid for HASH_FIXED or "
                "HASH_DYNAMIC tables"
            )
        if not isinstance(self.row_key_extractor, DynamicBucketRowKeyExtractor):
            if bucket_mode == BucketMode.HASH_DYNAMIC:
                raise RuntimeError("Dynamic bucket extractor is not configured")
        from pypaimon.index.dynamic_bucket import MAX_DYNAMIC_BUCKETS
        upper_bound = MAX_DYNAMIC_BUCKETS if bucket_mode == BucketMode.HASH_DYNAMIC else self.table.options.bucket()
        if not 0 <= bucket < upper_bound:
            raise ValueError('Bucket id must be between 0 and {}'.format(upper_bound - 1))
        data = self._prepare_arrow_data(data)
        if bucket_mode == BucketMode.HASH_DYNAMIC:
            partition = self.row_key_extractor.notify_precomputed_bucket_batch(data, bucket)
        else:
            partitions = self.row_key_extractor.extract_partitions_batch(data)
            if not partitions:
                return
            partition = tuple(partitions[0])
            if any(tuple(actual) != partition for actual in partitions):
                raise ValueError('A precomputed bucket group contained multiple partitions')
        if partition is None:
            return
        self._write_partition_bucket_batch(partition, bucket, data)

    def write_row(self, row):
        values_by_name = row_to_named_values(row, self.table.table_schema.fields)
        column_names = (
            self.file_store_write.write_cols
            if self.file_store_write.write_cols is not None
            else list(self.table.field_names)
        )
        require_columns(values_by_name, column_names, "write_row")
        require_columns(values_by_name, self.table.partition_keys, "write_row")
        from pypaimon.write.row_kind import skip_write_row
        if skip_write_row(self.table, values_by_name):
            return
        partition, bucket = (
            self.row_key_extractor.extract_partition_bucket_row(values_by_name)
        )
        self._write_partition_bucket_row(
            partition, bucket, row, values_by_name
        )

    def _write_partition_bucket_row(
        self, partition, bucket, row, values_by_name
    ):
        self.file_store_write.write_row(
            partition, bucket, row, values_by_name
        )

    def write_pandas(self, dataframe):
        write_cols = self.file_store_write.write_cols
        if write_cols is not None:
            # Column-subset write (append-only ``with_write_type``): build the
            # RecordBatch against the subset schema so the input only needs the
            # written columns, mirroring the ``write_arrow`` path.
            pa_schema = self._write_cols_pyarrow_schema(write_cols)
        else:
            pa_schema = self.table_pyarrow_schema
        record_batch = pa.RecordBatch.from_pandas(dataframe, schema=pa_schema)
        return self.write_arrow_batch(record_batch)

    def with_write_type(self, write_cols: List[str]):
        for col in write_cols:
            if col not in self.table_pyarrow_schema.names:
                raise ValueError(f"Column {col} is not in table schema.")
        if len(write_cols) == len(self.table_pyarrow_schema.names):
            write_cols = None
        self.file_store_write.write_cols = write_cols
        return self

    def with_blob_consumer(self, blob_consumer: BlobConsumer):
        if self.file_store_write.data_writers:
            raise RuntimeError(
                "with_blob_consumer must be called before any write operation."
            )
        self.file_store_write.blob_consumer = blob_consumer
        return self

    def with_blob_uri_reader_factory(self, uri_reader_factory):
        if self.file_store_write.data_writers:
            raise RuntimeError(
                "with_blob_uri_reader_factory must be called before any "
                "write operation."
            )
        self.file_store_write.blob_uri_reader_factory = uri_reader_factory
        return self

    def write_ray(
        self,
        dataset: "Dataset",
        overwrite: bool = False,
        concurrency: Optional[int] = None,
        ray_remote_args: Optional[Dict[str, Any]] = None,
        hash_fixed_precluster: str = "auto",
        static_partition: Optional[dict] = None,
    ) -> None:
        """
        Write a Ray Dataset to Paimon table.
        
        Args:
            dataset: Ray Dataset to write. This is a distributed data collection
                from Ray Data (ray.data.Dataset).
            overwrite: Whether to overwrite existing data. Defaults to False.
                Builder-level or static_partition overwrite mode takes precedence.
            concurrency: Optional max number of Ray tasks to run concurrently.
                By default, dynamically decided based on available resources.
            ray_remote_args: Optional kwargs passed to :func:`ray.remote` in write tasks.
                For example, ``{"num_cpus": 2, "max_retries": 3}``.
            hash_fixed_precluster: Pre-clustering mode. ``"auto"`` follows
                table options, ``"off"`` disables it, and ``"map_groups"``
                explicitly enables HASH_FIXED grouping.
            static_partition: Optional partition spec to overwrite. When set,
                the Ray write runs in overwrite mode for this partition and
                overrides any builder-level partition spec.
        """
        from pypaimon.write.ray_datasink import write_paimon_dataset

        overwrite_partition = self.static_partition
        if static_partition is not None:
            overwrite_partition = static_partition

        write_paimon_dataset(
            dataset,
            self.table,
            overwrite=overwrite,
            static_partition=overwrite_partition,
            concurrency=concurrency,
            ray_remote_args=ray_remote_args,
            hash_fixed_precluster=hash_fixed_precluster,
            **self._distributed_write_options(),
        )

    def _distributed_write_options(self) -> Dict[str, Any]:
        """Return options forwarded by ``write_ray`` to the Ray writer."""
        return {}

    def close(self):
        try:
            self.file_store_write.close()
        finally:
            self._release_prepared_indexes()

    def abort(self):
        try:
            self.file_store_write.abort()
        finally:
            abort = getattr(self.row_key_extractor, "abort", None)
            if abort is not None:
                abort()

    def _prepare_commit(self, commit_identifier) -> List[CommitMessage]:
        commit_messages = self.file_store_write._prepare_commit_messages(commit_identifier)
        prepare_indexes = getattr(self.row_key_extractor, "prepare_commit", None)
        index_changes = prepare_indexes() if prepare_indexes is not None else {}
        messages_by_bucket = {
            (tuple(message.partition), message.bucket): message
            for message in commit_messages
        }
        for (partition, bucket), changes in index_changes.items():
            message = messages_by_bucket.get((partition, bucket))
            if message is None:
                message = CommitMessage(
                    partition=partition,
                    bucket=bucket,
                    new_files=[],
                )
                commit_messages.append(message)
                messages_by_bucket[(partition, bucket)] = message
            message.index_adds.extend(changes.additions)
            message.index_deletes.extend(changes.deletions)
        # Hand off data, changelog and HASH indexes together. Until every
        # preparation succeeds, retain the metadata for retry and abort.
        self.file_store_write._release_prepared_files()
        self._release_prepared_indexes()
        return commit_messages

    def _release_prepared_indexes(self) -> None:
        release = getattr(self.row_key_extractor, "release_prepared", None)
        if release is not None:
            release()

    def _prepare_arrow_data(self, data):
        self._validate_pyarrow_schema(data.schema)
        data = normalize_arrow_strings(data)
        # Schema-only writers can normalize input without table options.
        table = getattr(self, 'table', None)
        if table is None:
            return data
        from pypaimon.write.row_kind import filter_write_batch
        return filter_write_batch(table, data)

    def _validate_pyarrow_schema(self, data_schema: pa.Schema):
        if self._is_compatible_pyarrow_schema(data_schema, self.table_pyarrow_schema):
            return

        write_cols = self.file_store_write.write_cols
        if write_cols is not None:
            write_cols_schema = self._write_cols_pyarrow_schema(write_cols)
            if self._is_compatible_pyarrow_schema(data_schema, write_cols_schema):
                return

        self._raise_inconsistent_schema(data_schema)

    def _is_compatible_pyarrow_schema(
            self, data_schema: pa.Schema, expected_schema: pa.Schema) -> bool:
        return arrow_schemas_compatible(
            data_schema, expected_schema, check_top_level_nullability=False, allow_binary_compatibility=True)

    def _write_cols_pyarrow_schema(self, write_cols: List[str]) -> pa.Schema:
        table_fields = {
            field.name: field for field in self.table_pyarrow_schema
        }
        return pa.schema([table_fields[col] for col in write_cols])

    def _raise_inconsistent_schema(self, data_schema: pa.Schema):
        raise ValueError(f"Input schema isn't consistent with table schema and write cols. "
                         f"Input schema is: {data_schema} "
                         f"Table schema is: {self.table_pyarrow_schema} "
                         f"Write cols is: {self.file_store_write.write_cols}")


class BatchTableWrite(TableWrite):
    def __init__(self, table, commit_user, static_partition: Optional[dict] = None,
                 *, restore_snapshot_id=None):
        super().__init__(table, commit_user, static_partition,
                         restore_snapshot_id=restore_snapshot_id)
        self.batch_committed = False

    def prepare_commit(self) -> List[CommitMessage]:
        if self.batch_committed:
            raise RuntimeError("BatchTableWrite only supports one-time committing.")
        self.batch_committed = True
        return self._prepare_commit(BATCH_COMMIT_IDENTIFIER)


class StreamTableWrite(TableWrite):

    def __init__(self, table, commit_user, *, restore_snapshot_id=None):
        super().__init__(table, commit_user, None,
                         restore_snapshot_id=restore_snapshot_id)

    def prepare_commit(self, commit_identifier) -> List[CommitMessage]:
        return self._prepare_commit(commit_identifier)
