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

"""Paimon writer capabilities shared by Rust core and the Python bridge."""

from unittest.mock import patch

import pyarrow as pa
import pytest

from pypaimon import CatalogFactory, Schema
from pypaimon.table.row.generic_row import GenericRowDeserializer
from pypaimon.write.write_dispatch import NativeTableWrite


pytestmark = pytest.mark.native_plan


def _table(tmp_path, schema, primary_key=False, options=None, partition_keys=None):
    catalog = CatalogFactory.create({'warehouse': str(tmp_path)})
    catalog.create_database('default', True)
    opts = {'file.format': 'parquet', 'write.native.enabled': 'true',
            'bucket': '1' if primary_key else '-1'}
    opts.update(options or {})
    catalog.create_table('default.t', Schema.from_pyarrow_schema(
        schema, primary_keys=['id'] if primary_key else [],
        partition_keys=partition_keys or [], options=opts), False)
    return catalog.get_table('default.t')


def _rows(table, native_read, all_files=False, chunk_shuffle=False):
    table = table.copy({'read.native.enabled': str(native_read).lower(),
                        'scan.native-plan.enabled': str(native_read).lower()})
    builder = table.new_read_builder()
    scan = builder.new_scan()
    if chunk_shuffle:
        scan.with_chunk_shuffle(seed=7, chunk_size=1)
    splits = (scan.plan_all() if all_files else scan.plan()).splits()
    read = builder.new_read()
    if native_read:
        with patch(
            'pypaimon.execution.python.read.table_read.PythonTableRead._create_split_read',
            side_effect=AssertionError('Python fallback')
        ):
            rows = read.to_arrow(splits).to_pylist()
    else:
        rows = read.to_arrow(splits).to_pylist()
    return sorted(rows, key=lambda row: row['id'])


@pytest.mark.parametrize('stream', [False, True])
@pytest.mark.parametrize('engine,expected', [
    ('first-row', {'id': 1, 'a': 1, 'b': 'first'}),
    ('partial-update', {'id': 1, 'a': 3, 'b': 'second'}),
    ('aggregation', {'id': 1, 'a': 6, 'b': 'second'}),
])
def test_native_merge_engines_within_and_across_commits(tmp_path, stream, engine, expected):
    schema = pa.schema([('id', pa.int64()), ('a', pa.int64()), ('b', pa.string())])
    options = {'merge-engine': engine}
    if engine == 'aggregation':
        options['fields.a.aggregate-function'] = 'sum'
    table = _table(tmp_path, schema, True, options)
    builder = (table.new_stream_write_builder() if stream else table.new_batch_write_builder())
    writer, commit = builder.new_write(), builder.new_commit()
    assert isinstance(writer, NativeTableWrite)
    try:
        for row in [{'id': 1, 'a': 1, 'b': 'first'}, {'id': 1, 'a': 2, 'b': 'second'}]:
            writer.write_arrow(pa.Table.from_pylist([row], schema=schema))
        if stream:
            commit.commit(writer.prepare_commit(1), 1)
        else:
            commit.commit(writer.prepare_commit())
            writer.close()
            commit.close()
            builder = table.new_batch_write_builder()
            writer, commit = builder.new_write(), builder.new_commit()
            assert isinstance(writer, NativeTableWrite)
        writer.write_arrow(pa.Table.from_pylist([{'id': 1, 'a': 3, 'b': None}], schema=schema))
        if stream:
            commit.commit(writer.prepare_commit(2), 2)
        else:
            commit.commit(writer.prepare_commit())
    finally:
        writer.close()
        commit.close()
    # Java first-row batch scans hide un-compacted L0 files; write scans expose them.
    for native_read in (False, True):
        assert _rows(table, native_read, engine == 'first-row') == [expected]


@pytest.mark.parametrize('stream', [False, True])
@pytest.mark.parametrize('data_evolution', [False, True])
def test_native_append_row_rolling_and_checkpoints(tmp_path, stream, data_evolution):
    schema = pa.schema([('id', pa.int64()), ('name', pa.string())])
    table = _table(tmp_path, schema, options={
        'target-file-row-num': '3',
        'row-tracking.enabled': str(data_evolution).lower(),
        'data-evolution.enabled': str(data_evolution).lower(),
    })
    builder = (table.new_stream_write_builder() if stream else table.new_batch_write_builder())
    writer, commit = builder.new_write(), builder.new_commit()
    assert isinstance(writer, NativeTableWrite)
    expected = []
    try:
        for checkpoint in range(2 if stream else 1):
            for ids in ([0, 1], [2, 3], [4]):
                rows = [{'id': i + checkpoint * 5, 'name': 'value'} for i in ids]
                expected.extend(rows)
                writer.write_arrow(pa.Table.from_pylist(rows, schema=schema))
            messages = writer.prepare_commit(checkpoint) if stream else writer.prepare_commit()
            counts = sorted(file.row_count for message in messages for file in message.new_files)
            # Java bundled writes may cross the limit by one input batch.
            assert sum(counts) == 5
            assert len(counts) >= 2
            assert max(counts) <= 4
            if stream:
                commit.commit(messages, checkpoint)
            else:
                commit.commit(messages)
    finally:
        writer.close()
        commit.close()
    for native_read in (False, True):
        assert _rows(table, native_read) == expected
    if data_evolution:
        assert table.snapshot_manager().get_latest_snapshot().next_row_id == len(expected)


@pytest.mark.parametrize('primary_key', [False, True])
def test_native_nested_and_fixed_binary_input(tmp_path, primary_key):
    schema = pa.schema([
        ('id', pa.int64()), ('bytes', pa.binary()),
        ('items', pa.list_(pa.struct([('label', pa.string()), ('value', pa.int64())]))),
        ('mapping', pa.map_(pa.string(), pa.list_(pa.int64()))),
    ])
    table = _table(tmp_path, schema, primary_key)
    input_schema = schema.set(1, pa.field('bytes', pa.binary(3)))
    rows = [
        {'id': 0, 'bytes': b'xyz', 'items': [], 'mapping': []},
        {'id': 1, 'bytes': b'abc', 'items': [{'label': 'a', 'value': None}, None],
         'mapping': [('a', [1, None]), ('b', [])]},
        {'id': 2, 'bytes': None, 'items': None, 'mapping': None},
        {'id': 3, 'bytes': b'def', 'items': [], 'mapping': [('a', None)]},
    ]
    builder = table.new_batch_write_builder()
    writer, commit = builder.new_write(), builder.new_commit()
    assert isinstance(writer, NativeTableWrite)
    try:
        # A sliced batch checks offsets and null parents in nested Arrow input.
        writer.write_arrow(pa.Table.from_pylist(rows, schema=input_schema).slice(1))
        assert writer._python_writer is None
        # Fixed binary must also work after native data has already been written.
        writer.write_arrow(pa.Table.from_pylist(rows[:1], schema=input_schema))
        commit.commit(writer.prepare_commit())
    finally:
        writer.close()
        commit.close()
    for native_read in (False, True):
        assert _rows(table, native_read) == rows


@pytest.mark.parametrize('mode', ['full', 'truncate(3)', 'counts'])
def test_native_primary_key_value_stats(tmp_path, mode):
    schema = pa.schema([('id', pa.int64()), ('value', pa.string())])
    table = _table(tmp_path, schema, True, {'metadata.stats-mode': mode})
    rows = [{'id': 1, 'value': 'abcdef'}, {'id': 2, 'value': None}]
    builder = table.new_batch_write_builder()
    writer, commit = builder.new_write(), builder.new_commit()
    assert isinstance(writer, NativeTableWrite)
    try:
        writer.write_arrow(pa.Table.from_pylist(rows, schema=schema))
        messages = writer.prepare_commit()
        files = [file for message in messages for file in message.new_files]
        assert len(files) == 1
        stats = files[0].value_stats
        assert stats.null_counts == [0, 1]
        expected_min, expected_max = {
            'full': ('abcdef', 'abcdef'), 'truncate(3)': ('abc', 'abd'), 'counts': (None, None),
        }[mode]
        assert GenericRowDeserializer.from_bytes(
            stats.min_values.data, table.fields).values[1] == expected_min
        assert GenericRowDeserializer.from_bytes(
            stats.max_values.data, table.fields).values[1] == expected_max
        commit.commit(messages)
    finally:
        writer.close()
        commit.close()
    for native_read in (False, True):
        assert _rows(table, native_read) == rows


@pytest.mark.parametrize('separate_commits', [False, True])
def test_native_partial_update_sequence_group_aggregation(tmp_path, separate_commits):
    schema = pa.schema([(name, pa.int64()) for name in ('id', 'seq', 'total', 'latest', 'free')])
    table = _table(tmp_path, schema, True, {
        'merge-engine': 'partial-update', 'fields.seq.sequence-group': 'total,latest',
        'fields.total.aggregate-function': 'sum',
    })
    rows = [
        {'id': 1, 'seq': 2, 'total': 10, 'latest': 20, 'free': 1},
        {'id': 1, 'seq': 1, 'total': 3, 'latest': 10, 'free': 2},
        {'id': 1, 'seq': 3, 'total': 7, 'latest': 30, 'free': None},
    ]
    groups = [[row] for row in rows] if separate_commits else [rows]
    for group in groups:
        builder = table.new_batch_write_builder()
        writer, commit = builder.new_write(), builder.new_commit()
        assert isinstance(writer, NativeTableWrite)
        try:
            for row in group:
                writer.write_arrow(pa.Table.from_pylist([row], schema=schema))
            commit.commit(writer.prepare_commit())
        finally:
            writer.close()
            commit.close()
    # Java aggregates every input, while non-aggregate fields follow sequence
    # groups and ungrouped fields keep the last non-null value in arrival order.
    assert _rows(table, True) == [{'id': 1, 'seq': 3, 'total': 20, 'latest': 30, 'free': 2}]


@pytest.mark.parametrize('engine', ['first-row', 'partial-update', 'aggregation'])
def test_native_ignore_delete_filters_retractions(tmp_path, engine):
    schema = pa.schema([('id', pa.int64()), ('value', pa.int64()), ('op', pa.string())])
    options = {'merge-engine': engine, 'ignore-delete': 'true', 'rowkind.field': 'op'}
    if engine == 'aggregation':
        options['fields.value.aggregate-function'] = 'sum'
    table = _table(tmp_path, schema, True, options)
    builder = table.new_batch_write_builder()
    writer, commit = builder.new_write(), builder.new_commit()
    assert isinstance(writer, NativeTableWrite)
    try:
        writer.write_arrow(pa.Table.from_pylist([
            {'id': 1, 'value': 10, 'op': '+I'}, {'id': 1, 'value': 99, 'op': '-D'},
            {'id': 2, 'value': 20, 'op': '-U'},
        ], schema=schema))
        commit.commit(writer.prepare_commit())
    finally:
        writer.close()
        commit.close()
    assert _rows(table, True, engine == 'first-row') == [{'id': 1, 'value': 10, 'op': '+I'}]


@pytest.mark.parametrize('chunk_shuffle', [False, True])
def test_native_data_evolution_partitioned_append_delete_and_time_travel(tmp_path, chunk_shuffle):
    schema = pa.schema([('id', pa.int64()), ('p', pa.string())])
    table = _table(tmp_path, schema, partition_keys=['p'], options={
        'row-tracking.enabled': 'true', 'data-evolution.enabled': 'true',
        'deletion-vectors.enabled': 'true', 'index-file-in-data-file-dir': 'true',
        'read.native.enabled': 'true',
    })
    rows = [{'id': 1, 'p': 'a/b'}, {'id': 2, 'p': 'b'}, {'id': 3, 'p': 'a/b'}]
    builder = table.new_batch_write_builder()
    writer, commit = builder.new_write(), builder.new_commit()
    assert isinstance(writer, NativeTableWrite)
    try:
        writer.write_arrow(pa.Table.from_pylist(rows, schema=schema))
        commit.commit(writer.prepare_commit())
    finally:
        writer.close()
        commit.close()
    read = table.new_read_builder().with_projection(['id', '_ROW_ID'])
    mapped = read.new_read().to_arrow(read.new_scan().plan().splits()).to_pylist()
    # Row IDs are allocated by file commit order, not logical ID/partition order.
    row_id = next(row['_ROW_ID'] for row in mapped if row['id'] == 1)
    builder = table.new_batch_write_builder()
    messages = builder.new_update().delete_by_row_id([row_id])
    commit = builder.new_commit()
    try:
        commit.commit(messages)
    finally:
        commit.close()
    for native_read in (False, True):
        assert _rows(table, native_read, chunk_shuffle=chunk_shuffle) == rows[1:]
        assert _rows(table.copy({'scan.snapshot-id': '1'}), native_read,
                     chunk_shuffle=chunk_shuffle) == rows
