# 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 unittest.mock import Mock, patch

import pyarrow as pa
import pytest

from pypaimon import CatalogFactory, Schema
from pypaimon.catalog.catalog_environment import CatalogEnvironment
from pypaimon.common.options.core_options import CoreOptions
from pypaimon.common.options.options import Options
from pypaimon.snapshot.snapshot import BATCH_COMMIT_IDENTIFIER
from pypaimon.table.file_store_table import FileStoreTable
from pypaimon.write.commit_message import CommitMessage
from pypaimon.execution.native.write.native_commit import (
    create_native_commit,
    native_runtime_available,
    native_messages_supported,
)
from pypaimon.write.table_write import StreamTableWrite


pytestmark = pytest.mark.python_write


def requires_native(test):
    # Exercise the companion Rust release in the Native CI job.
    test = pytest.mark.native_plan(test)
    return pytest.mark.skipif(
        not native_runtime_available(), reason='pypaimon-rust not installed')(test)


def _table(tmp_path, mode='append', backend='filesystem', catalog=None):
    options = {'warehouse': str(tmp_path / 'warehouse')}
    if backend == 'jdbc':
        options.update({'metastore': 'jdbc', 'uri': 'jdbc:sqlite:' + str(tmp_path / 'catalog.db')})
    if catalog is None:
        catalog = CatalogFactory.create(options)
        catalog.create_database('default', True)
    options = {'file.format': 'parquet', 'commit.native.enabled': 'true'}
    if mode == 'pk':
        options['bucket'] = '1'
    elif mode == 'de':
        options.update({'data-evolution.enabled': 'true', 'row-tracking.enabled': 'true'})
    catalog.create_table('default.t', Schema.from_pyarrow_schema(
        pa.schema([('id', pa.int64()), ('pt', pa.string())]),
        options=options, primary_keys=['id'] if mode == 'pk' else [],
        partition_keys=[] if mode in ('pk', 'unpartitioned') else ['pt']), False)
    table = catalog.get_table('default.t')
    if backend == 'path':
        table = FileStoreTable.from_path(table.table_path)
    if backend == 'jdbc':
        catalog.close()
    return table


def _prepare(builder, rows, identifier=None):
    writer = builder.new_write()
    try:
        writer.write_arrow(pa.Table.from_pylist(
            rows, schema=pa.schema([('id', pa.int64()), ('pt', pa.string())])))
        return writer.prepare_commit() if identifier is None else writer.prepare_commit(identifier)
    finally:
        writer.close()


def _rows(table):
    builder = table.new_read_builder()
    return sorted(builder.new_read().to_arrow(
        builder.new_scan().plan().splits()).to_pylist(), key=lambda row: row['id'])


def _must_not_fallback(commit, method='commit'):
    return patch('pypaimon.execution.python.write.file_store_commit.'
                 'FileStoreCommit.' + method,
                 side_effect=AssertionError('Python fallback'))


def _seed(table):
    builder = table.copy({'commit.native.enabled': 'false'}).new_batch_write_builder()
    commit = builder.new_commit()
    try:
        commit.commit(_prepare(builder, [
            {'id': 1, 'pt': 'a'}, {'id': 2, 'pt': 'b'}, {'id': 3, 'pt': None}]))
    finally:
        commit.close()


@pytest.mark.python_commit
def test_native_commit_is_opt_in():
    assert not CoreOptions(Options({})).native_commit_enabled()
    assert CoreOptions(Options({'commit.native.enabled': 'true'})).native_commit_enabled()


@pytest.mark.parametrize('backend', ['filesystem', 'path', 'jdbc'])
def test_non_rest_catalog_keeps_python_commit(tmp_path, backend):
    table = _table(tmp_path, backend=backend)
    assert create_native_commit(table, 'job') is None
    builder = table.new_batch_write_builder()
    commit = builder.new_commit()
    try:
        commit.commit(_prepare(builder, [{'id': 1, 'pt': 'a'}]))
        assert _rows(table) == [{'id': 1, 'pt': 'a'}]
    finally:
        commit.close()


def test_overwrite_builder_api_is_batch_only(tmp_path):
    table = _table(tmp_path)
    batch = table.new_batch_write_builder()
    assert batch.overwrite({'pt': 'a'}) is batch
    assert batch.static_partition == {'pt': 'a'}
    stream = table.new_stream_write_builder()
    with pytest.raises(AttributeError):
        stream.overwrite({'pt': 'a'})
    with pytest.raises(TypeError):
        StreamTableWrite(table, stream.commit_user, {'pt': 'a'})


@requires_native
@pytest.mark.parametrize('mode', ['append', 'pk'])
def test_native_batch_roundtrip_preserves_identity(tmp_path, native_rest_catalog, mode):
    table = _table(tmp_path, mode, catalog=native_rest_catalog)
    builder = table.new_batch_write_builder()
    rows = [{'id': 1, 'pt': 'a'}, {'id': 2, 'pt': None}]
    messages = _prepare(builder, rows)
    commit = builder.new_commit()
    try:
        with _must_not_fallback(commit):
            commit.commit(messages)
        snapshot = table.snapshot_manager().get_latest_snapshot()
        assert snapshot.commit_user == builder.commit_user
        assert snapshot.commit_identifier == BATCH_COMMIT_IDENTIFIER
        assert _rows(table) == rows
        with pytest.raises(RuntimeError, match='one-time'):
            commit.commit(messages)
    finally:
        commit.close()


@requires_native
def test_replaced_rest_table_rejects_stale_commit(tmp_path, native_rest_catalog):
    table = _table(tmp_path, catalog=native_rest_catalog)
    table.catalog_environment.uuid = 'stale-table-id'
    assert create_native_commit(table, 'job') is None


@requires_native
def test_native_stream_reuses_commit_user_and_identifiers(tmp_path, native_rest_catalog):
    table = _table(tmp_path, catalog=native_rest_catalog)
    builder = table.new_stream_write_builder()
    commit = builder.new_commit()
    try:
        with _must_not_fallback(commit):
            for identifier in (7, 8):
                commit.commit(_prepare(builder, [{'id': identifier, 'pt': None}], identifier), identifier)
                snapshot = table.snapshot_manager().get_latest_snapshot()
                assert snapshot.commit_user == builder.commit_user
                assert snapshot.commit_identifier == identifier
        assert _rows(table) == [{'id': 7, 'pt': None}, {'id': 8, 'pt': None}]
    finally:
        commit.close()


@requires_native
@pytest.mark.parametrize('mode,dynamic,spec', [
    ('append', True, {'pt': 'ignored'}),
    ('append', False, {'pt': 'a'}),
    ('pk', True, {}),
    ('unpartitioned', True, {}),
])
def test_native_overwrite_replaces_only_target_rows(
        tmp_path, native_rest_catalog, mode, dynamic, spec):
    table = _table(tmp_path, mode, catalog=native_rest_catalog).copy({
        'dynamic-partition-overwrite': str(dynamic).lower(), 'commit.user-prefix': 'python'})
    _seed(table)
    builder = table.new_batch_write_builder().overwrite(spec)
    commit = builder.new_commit()
    try:
        messages = _prepare(builder, [{'id': 4, 'pt': 'a'}])
        with _must_not_fallback(commit, 'overwrite'):
            commit.commit(messages)
        expected = [{'id': 4, 'pt': 'a'}]
        if table.partition_keys:
            expected = [{'id': 2, 'pt': 'b'}, {'id': 3, 'pt': None}] + expected
        assert _rows(table) == expected
        snapshot = table.snapshot_manager().get_latest_snapshot()
        assert snapshot.commit_user == builder.commit_user
        assert snapshot.commit_identifier == BATCH_COMMIT_IDENTIFIER
        assert snapshot.commit_kind == 'OVERWRITE'
        with pytest.raises(RuntimeError, match='one-time'):
            commit.commit(messages)
    finally:
        commit.close()


@requires_native
@pytest.mark.parametrize('mode,dynamic,spec,remaining', [
    ('append', True, {}, [1, 2, 3]),
    ('append', False, {'pt': 'a'}, [2, 3]),
    ('append', False, {'pt': None}, [1, 2]),
    ('append', False, {'pt': '__DEFAULT_PARTITION__'}, [1, 2]),
    ('append', False, {}, []),
    ('unpartitioned', True, {}, []),
    ('pk', True, {}, []),
])
def test_native_empty_overwrite_semantics(
        tmp_path, native_rest_catalog, mode, dynamic, spec, remaining):
    table = _table(tmp_path, mode, catalog=native_rest_catalog).copy({
        'dynamic-partition-overwrite': str(dynamic).lower()})
    _seed(table)
    builder = table.new_batch_write_builder().overwrite(spec)
    commit = builder.new_commit()
    try:
        with _must_not_fallback(commit, 'overwrite'):
            commit.commit([])
        assert [row['id'] for row in _rows(table)] == remaining
        snapshot = table.snapshot_manager().get_latest_snapshot()
        if remaining == [1, 2, 3]:
            assert snapshot.id == 1
        else:
            assert snapshot.id == 2
            assert snapshot.commit_user == builder.commit_user
            assert snapshot.commit_kind == 'OVERWRITE'
    finally:
        commit.close()


@requires_native
@pytest.mark.parametrize('value', ['off', '0', ' false '])
def test_native_overwrite_normalizes_python_boolean_option(tmp_path, native_rest_catalog, value):
    table = _table(tmp_path, catalog=native_rest_catalog).copy({
        'dynamic-partition-overwrite': value, 'snapshot.ignore-empty-commit': value})
    _seed(table)
    commit = table.new_batch_write_builder().overwrite({'pt': 'a'}).new_commit()
    try:
        with _must_not_fallback(commit, 'overwrite'):
            commit.commit([])
        assert [row['id'] for row in _rows(table)] == [2, 3]
    finally:
        commit.close()


@pytest.mark.parametrize('native', [False, pytest.param(True, marks=pytest.mark.native_plan)])
@pytest.mark.parametrize('case', ['unpartitioned', 'static-empty', 'static-missing', 'dynamic-empty'])
def test_empty_overwrite_records_java_snapshot(tmp_path, native_rest_catalog, native, case):
    if native and not native_runtime_available():
        pytest.skip('pypaimon-rust not installed')
    table = _table(tmp_path, 'unpartitioned' if case == 'unpartitioned' else 'append',
                   catalog=native_rest_catalog).copy({
                       'commit.native.enabled': str(native).lower(),
                       'dynamic-partition-overwrite': str(case == 'dynamic-empty').lower(),
                   })
    if case == 'static-missing':
        _seed(table)
    builder = table.new_batch_write_builder().overwrite(
        {'pt': 'missing'} if case.startswith('static') else {})
    commit = builder.new_commit()
    try:
        if native:
            with _must_not_fallback(commit, 'overwrite'):
                commit.commit([])
        else:
            commit.commit([])
        snapshot = table.snapshot_manager().get_latest_snapshot()
        if case == 'dynamic-empty':
            assert snapshot is None
        else:
            assert snapshot.id == (2 if case == 'static-missing' else 1)
            assert snapshot.commit_user == builder.commit_user
            assert snapshot.commit_kind == 'OVERWRITE'
            assert snapshot.total_record_count == (3 if case == 'static-missing' else 0)
        assert [row['id'] for row in _rows(table)] == ([1, 2, 3] if case == 'static-missing' else [])
    finally:
        commit.close()


@requires_native
@pytest.mark.parametrize('mode', ['batch', 'stream'])
@pytest.mark.parametrize('ignore', [True, False])
def test_native_empty_commit_preserves_python_option(
        tmp_path, native_rest_catalog, mode, ignore):
    table = _table(tmp_path, catalog=native_rest_catalog).copy({
        'snapshot.ignore-empty-commit': str(ignore).lower()})
    commit = getattr(table, 'new_' + mode + '_write_builder')().new_commit()
    try:
        with _must_not_fallback(commit):
            if mode == 'batch':
                commit.commit([])
            else:
                commit.commit([], 7)
        snapshot = table.snapshot_manager().get_latest_snapshot()
        if ignore:
            assert snapshot is None
        else:
            assert snapshot.commit_identifier == (BATCH_COMMIT_IDENTIFIER if mode == 'batch' else 7)
            assert snapshot.total_record_count == 0
    finally:
        commit.close()


@requires_native
@pytest.mark.parametrize('overwrite', [False, True])
def test_native_abort_removes_uncommitted_files(tmp_path, native_rest_catalog, overwrite):
    table = _table(tmp_path, catalog=native_rest_catalog)
    builder = table.new_batch_write_builder()
    if overwrite:
        builder.overwrite()
    messages = _prepare(builder, [{'id': 1, 'pt': None}])
    files = list(tmp_path.rglob('data-*.parquet'))
    assert files
    commit = builder.new_commit()
    try:
        with patch('pypaimon.execution.python.write.file_store_commit.'
                   'FileStoreCommit.abort',
                   side_effect=AssertionError('Python fallback')):
            commit.abort(messages)
        assert not any(path.exists() for path in files)
        assert table.snapshot_manager().get_latest_snapshot() is None
    finally:
        commit.close()


@requires_native
@pytest.mark.parametrize('serialized', [False, True])
def test_python_written_escaped_partition_supports_native_abort(
        tmp_path, native_rest_catalog, serialized):
    from pypaimon.write.commit_message_serializer import deserialize_commit_message, serialize_commit_message

    table = _table(tmp_path, catalog=native_rest_catalog)
    builder = table.new_batch_write_builder()
    messages = _prepare(builder, [{'id': 1, 'pt': 'a/b'}])
    file = messages[0].new_files[0]
    assert table.file_io.exists(file.file_path)
    assert '/pt=a%2Fb/' in file.file_path
    if serialized:
        messages = [deserialize_commit_message(serialize_commit_message(message, table.partition_keys_fields),
                                               table.partition_keys_fields) for message in messages]
    assert native_messages_supported(table, messages)

    commit = builder.new_commit()
    try:
        with patch('pypaimon.execution.python.write.file_store_commit.'
                   'FileStoreCommit.abort',
                   side_effect=AssertionError('Python fallback')):
            commit.abort(messages)
        assert not table.file_io.exists(file.file_path)
        assert table.snapshot_manager().get_latest_snapshot() is None
    finally:
        commit.close()


@pytest.mark.parametrize('failure', ['missing', 'construction', 'conversion'])
def test_preflight_failure_uses_python(tmp_path, failure):
    table = _table(tmp_path)
    builder = table.new_batch_write_builder()
    messages = _prepare(builder, [{'id': 1, 'pt': 'a'}])
    commit = builder.new_commit()
    native = Mock()
    with patch('pypaimon.execution.native.write.native_commit.create_native_commit', return_value=native) as create:
        if failure == 'missing':
            create.return_value = None
        elif failure == 'construction':
            create.side_effect = RuntimeError('unsupported FileIO')
        with patch('pypaimon.execution.native.write.native_commit.to_native_commit_messages',
                   side_effect=ValueError('unsupported payload')):
            commit.commit(messages)
    native.commit.assert_not_called()
    assert _rows(table) == [{'id': 1, 'pt': 'a'}]
    commit.close()


@pytest.mark.parametrize('method', ['commit', 'abort'])
@pytest.mark.parametrize('overwrite', [False, True])
def test_native_mutation_failure_never_falls_back_or_aborts(tmp_path, method, overwrite):
    table = _table(tmp_path)
    builder = table.new_batch_write_builder()
    if overwrite:
        builder.overwrite()
    messages = _prepare(builder, [{'id': 1, 'pt': 'a'}])
    commit = builder.new_commit()
    native = Mock()
    getattr(native, method).side_effect = OSError('outcome unknown')
    with patch('pypaimon.execution.native.write.native_commit.create_native_commit', return_value=native), \
            patch('pypaimon.execution.native.write.native_commit.to_native_commit_messages', return_value=['wire']), \
            patch('pypaimon.execution.python.write.file_store_commit.'
                  'FileStoreCommit.commit') as fallback, \
            patch('pypaimon.execution.python.write.file_store_commit.'
                  'FileStoreCommit.overwrite') as fallback_overwrite, \
            patch('pypaimon.execution.python.write.file_store_commit.'
                  'FileStoreCommit.abort') as abort:
        with pytest.raises(OSError, match='outcome unknown'):
            getattr(commit, method)(messages)
        fallback.assert_not_called()
        fallback_overwrite.assert_not_called()
        abort.assert_not_called()
        if method == 'commit':
            native.abort.assert_not_called()
            with pytest.raises(RuntimeError, match='one-time'):
                commit.commit(messages)
    assert list(tmp_path.rglob('data-*.parquet'))
    commit.close()


@requires_native
@pytest.mark.parametrize('overwrite', [False, True])
def test_publication_response_loss_does_not_duplicate_or_delete_files(
        tmp_path, native_rest_catalog, overwrite):
    table = _table(tmp_path, catalog=native_rest_catalog)
    builder = table.new_batch_write_builder()
    if overwrite:
        builder.overwrite()
    messages = _prepare(builder, [{'id': 1, 'pt': None}])
    native = create_native_commit(table, builder.commit_user, builder.static_partition)
    proxy = Mock(wraps=native)

    def publish_then_fail(*args):
        native.commit(*args)
        raise OSError('response lost')

    proxy.commit.side_effect = publish_then_fail
    commit = builder.new_commit()
    try:
        with patch('pypaimon.execution.native.write.native_commit.create_native_commit', return_value=proxy), \
                _must_not_fallback(commit, 'overwrite' if overwrite else 'commit'), \
                patch('pypaimon.execution.python.write.file_store_commit.'
                      'FileStoreCommit.abort',
                      side_effect=AssertionError('abort')):
            with pytest.raises(OSError, match='response lost'):
                commit.commit(messages)
        assert table.snapshot_manager().get_latest_snapshot().id == 1
        assert _rows(table) == [{'id': 1, 'pt': None}]
        proxy.abort.assert_not_called()
    finally:
        commit.close()


@pytest.mark.parametrize('properties', [{}, {'source': 'python'}])
@pytest.mark.parametrize('overwrite', [False, True])
def test_non_rest_snapshot_properties_keep_python_commit(tmp_path, properties, overwrite):
    table = _table(tmp_path)
    builder = table.new_batch_write_builder()
    if overwrite:
        builder.overwrite()
    commit = builder.new_commit()
    with patch('pypaimon.execution.native.write.native_commit.create_native_commit',
               wraps=create_native_commit) as create:
        commit.commit(_prepare(builder, [{'id': 1, 'pt': None}]), snapshot_properties=properties)
        create.assert_called_once()
        assert commit._native_commit is None
    assert table.snapshot_manager().get_latest_snapshot().properties == (properties or None)
    commit.close()


@requires_native
@pytest.mark.parametrize('warmup', [False, True])
def test_callbacks_added_after_construction_use_native(
        tmp_path, native_rest_catalog, warmup):
    if warmup and not native_runtime_available():
        pytest.skip('native warmup requires the commit bindings')
    table = _table(tmp_path, catalog=native_rest_catalog)
    builder = table.new_stream_write_builder()
    commit = builder.new_commit()
    if warmup:
        with _must_not_fallback(commit):
            commit.commit(_prepare(builder, [{'id': 6, 'pt': None}], 6), 6)
    callback = Mock()
    commit.add_commit_callback(callback)
    with _must_not_fallback(commit):
        commit.commit(_prepare(builder, [{'id': 1, 'pt': None}], 7), 7)
    callback.call.assert_called_once()
    context = callback.call.call_args[0][0]
    assert context.identifier == 7
    assert context.snapshot.id == (2 if warmup else 1)
    assert sum(entry.file.row_count for entry in context.commit_entries) == 1
    commit.close()
    callback.close.assert_called_once()


def test_truncate_keeps_python_when_native_publication_is_unavailable(tmp_path):
    table = _table(tmp_path)
    _seed(table)
    with patch('pypaimon.execution.native.write.native_commit.create_native_commit', return_value=None) as create:
        for method, args in [('truncate_partitions', ([{'pt': 'a'}],)), ('truncate_table', ())]:
            commit = table.new_batch_write_builder().new_commit()
            try:
                getattr(commit, method)(*args)
            finally:
                commit.close()
        assert create.call_count == 2
    assert _rows(table) == []


def test_overwrite_conversion_failure_preserves_partition_scope(tmp_path):
    table = _table(tmp_path).copy({'dynamic-partition-overwrite': 'false'})
    _seed(table)
    builder = table.new_batch_write_builder().overwrite({'pt': 'a'})
    commit = builder.new_commit()
    native = Mock()
    try:
        messages = _prepare(builder, [{'id': 4, 'pt': 'a'}])
        with patch('pypaimon.execution.native.write.native_commit.create_native_commit', return_value=native), \
                patch('pypaimon.execution.native.write.native_commit.to_native_commit_messages',
                      side_effect=ValueError('unsupported payload')):
            commit.commit(messages)
        native.commit.assert_not_called()
        native.abort.assert_not_called()
        assert _rows(table) == [{'id': 2, 'pt': 'b'}, {'id': 3, 'pt': None}, {'id': 4, 'pt': 'a'}]
        assert table.snapshot_manager().get_latest_snapshot().commit_user == builder.commit_user
    finally:
        commit.close()


def test_overwrite_callbacks_select_python(tmp_path):
    table = _table(tmp_path)
    builder = table.new_batch_write_builder().overwrite()
    commit = builder.new_commit()
    callback = Mock()
    commit.add_commit_callback(callback)
    with patch(
            'pypaimon.execution.native.write.native_commit.create_native_commit',
            wraps=create_native_commit) as create:
        commit.commit(_prepare(builder, [{'id': 1, 'pt': 'a'}]))
        create.assert_called_once()
        assert commit._native_commit is None
    assert _rows(table) == [{'id': 1, 'pt': 'a'}]
    callback.call.assert_called_once()
    commit.close()
    callback.close.assert_called_once()


def test_disabled_option_never_initializes_native(tmp_path):
    table = _table(tmp_path).copy({'commit.native.enabled': 'false'})
    builder = table.new_batch_write_builder()
    commit = builder.new_commit()
    with patch('pypaimon.execution.native.write.native_commit.create_native_commit') as create:
        commit.commit(_prepare(builder, [{'id': 1, 'pt': None}]))
        create.assert_not_called()
    assert _rows(table) == [{'id': 1, 'pt': None}]
    commit.close()


@pytest.mark.parametrize('kind', ['custom-env', 'custom-io'])
def test_incompatible_publication_environment_is_not_reconstructed(
        tmp_path, native_rest_catalog, kind):
    table = _table(tmp_path, catalog=native_rest_catalog)
    if kind == 'custom-env':
        class CustomEnvironment(CatalogEnvironment):
            pass
        table.catalog_environment = CustomEnvironment()
    else:
        table.file_io = Mock()
    with patch('pypaimon.execution.native.write.native_commit.native_runtime_available', return_value=True), \
            patch('pypaimon.execution.native.write.native_commit._native_rest_table') as resolve:
        assert create_native_commit(table, 'job') is None
        resolve.assert_not_called()


@pytest.mark.parametrize('option', ['hadoop_conf', 'prefer_io_loader', 'fallback_io_loader'])
def test_inactive_context_loader_fields_do_not_disable_native_commit(tmp_path, native_rest_catalog, option):
    from pypaimon.execution.native.write.native_commit import _rest_catalog_supported
    table = _table(tmp_path, catalog=native_rest_catalog)
    unused = Mock(side_effect=AssertionError('Inactive IO loader was invoked'))
    setattr(table.catalog_environment.catalog_loader.context(), option, unused)
    assert _rest_catalog_supported(table)
    unused.assert_not_called()


def test_missing_runtime_falls_back_without_reconstructing_table(
        tmp_path, native_rest_catalog):
    table = _table(tmp_path, catalog=native_rest_catalog)
    with patch('pypaimon.execution.native.write.native_commit.native_runtime_available', return_value=False), \
            patch('pypaimon.execution.native.write.native_commit._native_rest_table') as resolve:
        assert create_native_commit(table, 'job') is None
        resolve.assert_not_called()


def test_preassigned_row_id_messages_use_native_validation(
        tmp_path, native_rest_catalog):
    table = _table(tmp_path, 'de', catalog=native_rest_catalog)
    assert native_messages_supported(table, [CommitMessage((), 0, [])])
    assert native_messages_supported(table, [CommitMessage((), 0, [], check_from_snapshot=7)])
    messages = _prepare(table.new_batch_write_builder(), [{'id': 1, 'pt': 'a'}])
    messages[0].new_files[0].first_row_id = 1
    messages[0].check_from_snapshot = 7
    assert native_messages_supported(table, messages)
    assert not native_messages_supported(table, [CommitMessage((), 0, [], compact_after=[Mock()])])


@requires_native
@pytest.mark.parametrize('mode', ['append', 'de'])
def test_custom_manifest_target_uses_native_commit(tmp_path, native_rest_catalog, mode):
    from pypaimon.manifest.manifest_list_manager import ManifestListManager

    table = _table(tmp_path, mode, catalog=native_rest_catalog).copy({
        'manifest.target-file-size': '1 B'})
    builder = table.new_batch_write_builder()
    commit = builder.new_commit()
    try:
        messages = _prepare(builder, [{'id': 4, 'pt': 'a'}, {'id': 5, 'pt': 'b'}])
        with _must_not_fallback(commit):
            commit.commit(messages)
        assert _rows(table) == [{'id': 4, 'pt': 'a'}, {'id': 5, 'pt': 'b'}]
        snapshot = table.snapshot_manager().get_latest_snapshot()
        metas = ManifestListManager(table).read_delta(snapshot)
        assert len(metas) == 1  # Java checks only at multiples of 1000 records.
        assert metas[0].num_added_files == 2
    finally:
        commit.close()


def test_close_releases_python_resources_even_if_native_close_fails(tmp_path):
    commit = _table(tmp_path).new_batch_write_builder().new_commit()
    from pypaimon.execution.python.write.table_commit import create_python_commit
    commit._python_commit = create_python_commit(commit)
    commit._native_commit = Mock()
    commit._native_commit.close.side_effect = OSError('close failure')
    with patch('pypaimon.execution.python.write.file_store_commit.'
               'FileStoreCommit.close') as close:
        with pytest.raises(OSError, match='close failure'):
            commit.close()
        close.assert_called_once()


@requires_native
@pytest.mark.parametrize('mode', ['append', 'pk', 'de'])
@pytest.mark.parametrize('overwrite', [False, True])
def test_native_callbacks_keep_python_context_and_allow_native_read(
        tmp_path, native_rest_catalog, mode, overwrite):
    from pypaimon.manifest.schema.manifest_entry import ManifestEntry
    from pypaimon.table.row.generic_row import GenericRow
    from pypaimon.write.commit_callback import CommitCallback, CommitCallbackContext

    table = _table(tmp_path, mode, catalog=native_rest_catalog)
    table = table.copy({
        'scan.native-plan.enabled': 'true', 'read.native.enabled': 'true',
        'dynamic-partition-overwrite': 'false'})
    builder = table.new_batch_write_builder()
    if overwrite:
        _seed(table)
        builder.overwrite()
    calls = []

    class ReadingCallback(CommitCallback):
        def call(self, context):
            assert isinstance(context, CommitCallbackContext)
            assert all(isinstance(entry, ManifestEntry) for entry in context.commit_entries)
            assert all(isinstance(entry.partition, GenericRow) for entry in context.commit_entries)
            # Re-enter Rust's runtime from the Python callback after publication.
            with patch(
                'pypaimon.execution.python.read.table_read.PythonTableRead._create_split_read',
                side_effect=AssertionError('callback read fell back')
            ):
                calls.append((context, _rows(table)))

    commit = builder.new_commit()
    callback = ReadingCallback()
    follower = Mock()
    commit.add_commit_callback(callback)
    commit.add_commit_callback(follower)
    rows = [{'id': 9, 'pt': 'a/b%'}]
    messages = _prepare(builder, rows)
    paths = [file.file_path for message in messages for file in message.new_files]
    try:
        with _must_not_fallback(commit, 'overwrite' if overwrite else 'commit'):
            commit.commit(messages, snapshot_properties={'source': 'callback-test'})
        assert len(calls) == 1
        context, actual_rows = calls[0]
        assert actual_rows == rows
        assert context.identifier == BATCH_COMMIT_IDENTIFIER
        assert context.snapshot.properties == {'source': 'callback-test'}
        assert context.snapshot == table.snapshot_manager().get_latest_snapshot()
        adds = [entry for entry in context.commit_entries if entry.kind == 0]
        assert [entry.file.file_path for entry in adds] == paths
        assert all(table.file_io.exists(file_path) for file_path in paths)
        if mode == 'de':
            assert all(entry.file.first_row_id is not None for entry in adds)
            assert all(entry.file.min_sequence_number == context.snapshot.id for entry in adds)
        if overwrite:
            deletes = [entry for entry in context.commit_entries if entry.kind == 1]
            assert deletes
            assert all(entry.file.file_path for entry in deletes)
        follower.call.assert_called_once_with(context)
    finally:
        commit.close()
    follower.close.assert_called_once()


@requires_native
@pytest.mark.parametrize('lose_response', [False, True])
@pytest.mark.parametrize('callback_fails', [False, True])
def test_native_callback_recovery_and_error_preserve_files(
        tmp_path, native_rest_catalog, lose_response, callback_fails):
    from pypaimon.tests.rest.rest_server import RESTCatalogServer

    table = _table(tmp_path, 'de', catalog=native_rest_catalog)
    table = table.copy({'commit.min-retry-wait': '0 ms', 'commit.max-retry-wait': '0 ms'})
    builder = table.new_batch_write_builder()
    messages = _prepare(builder, [{'id': 1, 'pt': 'a/b%'}])
    paths = [file.file_path for message in messages for file in message.new_files]
    commit = builder.new_commit()
    callback = Mock()
    if callback_fails:
        callback.call.side_effect = LookupError('notification failed')
    commit.add_commit_callback(callback)
    follower = Mock()
    commit.add_commit_callback(follower)
    publish = RESTCatalogServer._table_commit_handle
    attempts = []

    def publish_then_lose_response(server, *args, **kwargs):
        result = publish(server, *args, **kwargs)
        attempts.append(result[1])
        assert result[1] == 200
        # A malformed successful response leaves publication outcome uncertain.
        return ('not-json', 200) if lose_response else result

    try:
        with patch.object(RESTCatalogServer, '_table_commit_handle', publish_then_lose_response), \
                _must_not_fallback(commit), \
                patch('pypaimon.execution.python.write.file_store_commit.'
                      'FileStoreCommit.abort',
                      side_effect=AssertionError('abort')):
            if callback_fails:
                with pytest.raises(LookupError, match='notification failed'):
                    commit.commit(messages)
            else:
                commit.commit(messages)
        assert attempts == [200], 'notification failure must not republish the snapshot'
        context = callback.call.call_args[0][0]
        assert context.snapshot.id == 1
        assert context.snapshot.next_row_id == 1
        assert context.commit_entries[0].file.first_row_id == 0
        assert context.commit_entries[0].file.file_path == paths[0]
        assert tuple(context.commit_entries[0].partition.values) == ('a/b%',)
        assert _rows(table) == [{'id': 1, 'pt': 'a/b%'}]
        assert all(table.file_io.exists(file_path) for file_path in paths)
        callback.call.assert_called_once()
        if callback_fails:
            follower.call.assert_not_called()
        else:
            follower.call.assert_called_once_with(context)
    finally:
        commit.close()
    callback.close.assert_called_once()
    follower.close.assert_called_once()


@requires_native
def test_native_callback_empty_commit_and_prepublication_failure(tmp_path, native_rest_catalog):
    table = _table(tmp_path, catalog=native_rest_catalog).copy({'snapshot.ignore-empty-commit': 'false'})
    builder = table.new_stream_write_builder()
    commit = builder.new_commit()
    callback = Mock()
    commit.add_commit_callback(callback)
    try:
        with _must_not_fallback(commit):
            commit.commit([], 1)
        context = callback.call.call_args[0][0]
        assert context.snapshot.id == 1
        assert context.identifier == 1
        assert context.commit_entries == []
        bad = _prepare(builder, [{'id': 1, 'pt': None}], 2)
        # A repeated file entry must fail before publication and notification.
        with _must_not_fallback(commit), pytest.raises(ValueError, match='Duplicate'):
            commit.commit(bad + bad, 2)
        callback.call.assert_called_once()
        assert table.snapshot_manager().get_latest_snapshot().id == 1
    finally:
        commit.close()


@requires_native
def test_native_callbacks_added_between_commits_share_context_and_close_once(
        tmp_path, native_rest_catalog):
    table = _table(tmp_path, catalog=native_rest_catalog)
    builder = table.new_stream_write_builder()
    commit = builder.new_commit()
    first, second = Mock(), Mock()
    events = []

    def first_call(context):
        events.append(('first', context.identifier, context))
        # Preserve Python's shared Context contract between registered callbacks.
        context.observed = True

    def second_call(context):
        assert context.observed
        events.append(('second', context.identifier, context))

    first.call.side_effect = first_call
    second.call.side_effect = second_call
    first.close.side_effect = OSError('close failed')
    commit.add_commit_callback(first)
    try:
        with _must_not_fallback(commit):
            commit.commit(_prepare(builder, [{'id': 1, 'pt': None}], 1), 1)
            commit.add_commit_callback(second)
            commit.commit(_prepare(builder, [{'id': 2, 'pt': None}], 2), 2)
            commit.commit(_prepare(builder, [{'id': 3, 'pt': None}], 3), 3)
        assert [(name, identifier) for name, identifier, _ in events] == [
            ('first', 1), ('first', 2), ('second', 2), ('first', 3), ('second', 3)]
        assert events[1][2] is events[2][2]
        assert events[3][2] is events[4][2]
    finally:
        commit.close()
    first.close.assert_called_once()
    second.close.assert_called_once()


@requires_native
@pytest.mark.parametrize('close', [False, True])
def test_native_commit_callback_cycle_is_collected(tmp_path, native_rest_catalog, close):
    import gc
    import weakref

    table = _table(tmp_path, catalog=native_rest_catalog)
    builder = table.new_stream_write_builder()
    commit = builder.new_commit()
    callback = Mock()
    callback.owner = commit
    reference = weakref.ref(callback)
    commit.add_commit_callback(callback)
    with _must_not_fallback(commit):
        commit.commit(_prepare(builder, [{'id': 1, 'pt': None}], 1), 1)
    if close:
        commit.close()
    del callback, commit
    gc.collect()
    assert reference() is None
