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

import logging
import uuid
import pyarrow as pa
from typing import Optional, Tuple, Dict

from pypaimon.execution.python.write.format_file_writer import (
    write_blob_file
)
from pypaimon.common.options.core_options import CoreOptions
from pypaimon.data.timestamp import Timestamp
from pypaimon.table.row.blob import (
    BlobConsumer,
    video_payload_descriptor,
)
from pypaimon.execution.python.write.writer.append_only_data_writer import AppendOnlyDataWriter
from pypaimon.execution.python.write.writer.blob_file_writer import BlobFileWriter
from pypaimon.execution.python.write.writer.video_group import VideoGroupRollingPolicy

logger = logging.getLogger(__name__)


class BlobWriter(AppendOnlyDataWriter):

    def __init__(self, table, partition: Tuple, bucket: int, max_seq_number: int, blob_column: str,
                 options: Dict[str, str] = None, blob_consumer: Optional[BlobConsumer] = None,
                 video: bool = False, uri_reader_factory=None):
        super().__init__(table, partition, bucket, max_seq_number,
                         options, write_cols=[blob_column])

        self.video = video
        if video and blob_consumer is not None:
            raise ValueError(
                f"BlobConsumer is not supported for video frame field '{blob_column}'."
            )
        self.file_format = (
            CoreOptions.FILE_FORMAT_VIDEO
            if video
            else CoreOptions.FILE_FORMAT_BLOB
        )

        # Store blob column name for use in metadata creation
        self.blob_column = blob_column

        options = self.table.options
        self.blob_target_file_size = CoreOptions.blob_target_file_size(options)
        # Use the effective options (constructor-provided), consistent with the other accessors.
        self.blob_copy_buffer_size = self.options.blob_copy_buffer_size()

        self._blob_consumer = blob_consumer
        self._uri_reader_factory = uri_reader_factory
        self.current_writer: Optional[BlobFileWriter] = None
        self.current_file_path: Optional[str] = None
        self.record_count = 0

        self.file_uuid = str(uuid.uuid4())
        self.file_count = 0
        self._video_group_policy = VideoGroupRollingPolicy() if video else None

        logger.info(f"Initialized BlobWriter with blob file format, blob_target_file_size={self.blob_target_file_size}")

    def _check_and_roll_if_needed(self):
        # Rolling here is driven by the size of the external blobs, which the
        # buffered descriptors say nothing about, so there is no cheap count to
        # check first: every write drains the buffer.
        pending = self._buffer.take()
        if pending is None:
            return

        # Always write blob rows one-by-one so rolling uses actual blob bytes size rather than
        # in-memory serialized descriptor size.
        for i in range(pending.num_rows):
            row_data = pending.slice(i, 1)
            next_group = video_payload_descriptor(row_data.column(0)[0])
            self._roll_before_video_group(next_group)
            self._write_row_to_file(row_data)
            self.record_count += 1
            if self._video_group_policy is not None:
                self._video_group_policy.record(next_group)

            if self.rolling_file():
                if (
                    self._video_group_policy is None
                    or not self._video_group_policy.defer_roll()
                ):
                    self.close_current_writer()

    def _write_row_to_file(self, row_data: pa.Table):
        """Write a single row to the current blob file. Opens a new file if needed."""
        if row_data.num_rows == 0:
            return

        if self.current_writer is None:
            self.open_current_writer()

        self.current_writer.write_row(row_data)
        # This ensures each row has a unique sequence number for data versioning and consistency
        self.sequence_generator.next()

    def write_blob(self, value, arrow_type=pa.large_binary()):
        next_group = video_payload_descriptor(value)
        self._roll_before_video_group(next_group)
        if self.current_writer is None:
            self.open_current_writer()

        self.current_writer.write_blob(self.blob_column, arrow_type, value)
        self.sequence_generator.next()
        self.record_count += 1
        if self._video_group_policy is not None:
            self._video_group_policy.record(next_group)

        if self.rolling_file():
            if (
                self._video_group_policy is None
                or not self._video_group_policy.defer_roll()
            ):
                self.close_current_writer()

    def open_current_writer(self):
        file_name = (f"{CoreOptions.data_file_prefix(self.options)}"
                     f"{self.file_uuid}-{self.file_count}.{self.file_format}")
        self.file_count += 1  # Increment counter for next file
        file_path = self._generate_file_path(file_name)
        self.current_file_path = file_path
        self.current_writer = BlobFileWriter(
            self.file_io,
            file_path,
            blob_consumer=self._blob_consumer,
            copy_buffer_size=self.blob_copy_buffer_size,
            video=self.video,
            uri_reader_factory=self._uri_reader_factory,
        )

    def rolling_file(self) -> bool:
        if self.current_writer is None:
            return False

        return (
            self.current_writer.row_count >= self.target_file_row_num
            or self.current_writer.reach_target_size(self.blob_target_file_size)
        )

    def should_roll_before_group(self, row_count: int) -> bool:
        return (
            self._video_group_policy is not None
            and self.current_writer is not None
            and (
                self._video_group_policy.pending_roll
                or self.current_writer.row_count + row_count
                > self.target_file_row_num
            )
        )

    def close_current_writer(self):
        """Close current writer and create metadata."""
        if self.current_writer is None:
            return

        file_size = self.current_writer.close()
        file_name = self.current_file_path.split('/')[-1]
        row_count = self.current_writer.row_count

        # Determine if this is an external path
        is_external_path = self.external_path_provider is not None
        external_path_str = self.current_file_path if is_external_path else None

        self._add_file_metadata(file_name, self.current_file_path, row_count, file_size, external_path_str)

        self.current_writer = None
        self.current_file_path = None
        if self._video_group_policy is not None:
            self._video_group_policy.reset()

    def _roll_before_video_group(self, next_group):
        if (
            self._video_group_policy is not None
            and self.current_writer is not None
            and self._video_group_policy.should_roll_before(next_group)
        ):
            self.close_current_writer()

    def _write_data_to_file(self, data):
        """
        Keep a fallback path for direct blob table writes while preserving the writer uuid+counter
        naming behavior.
        """
        if data.num_rows == 0:
            return

        # This ensures each row gets a unique sequence number, matching the behavior expected
        for _ in range(data.num_rows):
            self.sequence_generator.next()

        file_name = f"data-{self.file_uuid}-{self.file_count}.{self.file_format}"
        self.file_count += 1
        file_path = self._generate_file_path(file_name)

        write_blob_file(self.file_io, file_path, data)

        file_size = self.file_io.get_file_size(file_path)

        is_external_path = self.external_path_provider is not None
        external_path_str = file_path if is_external_path else None

        # Reuse _add_file_metadata for consistency (blob table is append-only, no primary keys)
        self._add_file_metadata(file_name, file_path, data, file_size, external_path_str)

    def _add_file_metadata(self, file_name: str, file_path: str, data_or_row_count, file_size: int,
                           external_path: Optional[str] = None):
        """Add file metadata to committed_files."""
        from pypaimon.manifest.schema.data_file_meta import DataFileMeta
        from pypaimon.manifest.schema.simple_stats import SimpleStats
        from pypaimon.table.row.generic_row import GenericRow
        from pypaimon.schema.data_types import PyarrowFieldParser

        # Handle both Table and row_count
        if isinstance(data_or_row_count, pa.Table):
            data = data_or_row_count
            row_count = data.num_rows
            data_fields = PyarrowFieldParser.to_paimon_schema(data.schema)
            # Compute statistics across all batches, not just the first one
            # This ensures correct min/max/null_counts when data has multiple batches
            column_stats = {
                field.name: self._get_column_stats(data, field.name)
                for field in data_fields
            }
            min_value_stats = [column_stats[field.name]['min_values'] for field in data_fields]
            max_value_stats = [column_stats[field.name]['max_values'] for field in data_fields]
            value_null_counts = [column_stats[field.name]['null_counts'] for field in data_fields]
        else:
            # row_count only (from BlobFileWriter)
            row_count = data_or_row_count
            data_fields = [self.table.field_dict[self.blob_column]]
            min_value_stats = [None]
            max_value_stats = [None]
            value_null_counts = [0]

        min_seq = self.sequence_generator.current - row_count
        max_seq = self.sequence_generator.current - 1
        self.sequence_generator.start = self.sequence_generator.current

        self.committed_files.append(DataFileMeta.create(
            file_name=file_name,
            file_size=file_size,
            row_count=row_count,
            min_key=GenericRow([], []),
            max_key=GenericRow([], []),
            key_stats=SimpleStats(GenericRow([], []), GenericRow([], []), []),
            value_stats=SimpleStats(
                GenericRow(min_value_stats, data_fields),
                GenericRow(max_value_stats, data_fields),
                value_null_counts),
            min_sequence_number=min_seq,
            max_sequence_number=max_seq,
            schema_id=self.table.table_schema.id,
            level=0,
            extra_files=[],
            creation_time=Timestamp.now().to_millis_timestamp(),
            delete_row_count=0,
            file_source=0,  # FileSource.APPEND = 0
            value_stats_cols=None,
            external_path=external_path,
            first_row_id=None,
            write_cols=self.write_cols,
            file_path=file_path,
        ))

    def prepare_commit(self):
        """Prepare commit, preserving blob files in write/rolling order."""
        # Close current file if open.
        if self.current_writer is not None:
            self.close_current_writer()

        # Call parent to flush anything left in the buffer.
        return super().prepare_commit()

    def close(self):
        """Close current writer if open."""
        # Close current file if open.
        if self.current_writer is not None:
            self.close_current_writer()

        # Call parent to flush anything left in the buffer.
        super().close()

    def delete_file_upon_abort(self) -> bool:
        return self._blob_consumer is None

    def abort(self):
        if self.current_writer is not None:
            try:
                self.current_writer.abort()
            except Exception as e:
                logger.warning(f"Error aborting blob writer: {e}", exc_info=e)
            self.current_writer = None
            self.current_file_path = None
        if self._video_group_policy is not None:
            self._video_group_policy.reset()
        if not self.delete_file_upon_abort():
            self._buffer.reset()
            self.committed_files.clear()
        else:
            super().abort()

    @staticmethod
    def _get_column_stats(data_or_batch, column_name: str):
        """
        Compute column statistics for a column in a Table or RecordBatch.
        """
        # Handle both Table and RecordBatch
        if isinstance(data_or_batch, pa.Table):
            column_array = data_or_batch.column(column_name)
        else:
            column_array = data_or_batch.column(column_name)

        # For blob data, don't generate min/max values
        return {
            "min_values": None,
            "max_values": None,
            "null_counts": column_array.null_count,
        }
