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

"""
Clickbench benchmark for Paimon file formats.

Downloads the Clickbench hits.parquet dataset and compares compression ratios
and read performance across Parquet, ORC, and Vortex formats in Paimon tables.

Usage:
    python benchmarks/clickbench_format.py [--rows N] [--data-path PATH]

    --rows N         Number of rows to use (default: 1_000_000, use 0 for full dataset)
    --data-path PATH Path to existing hits.parquet (skips download if provided)
"""

import argparse
import os
import random
import shutil
import sys
import tempfile
import time
from pathlib import Path

import pyarrow as pa
import pyarrow.parquet as pq

# Add project root to path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

from pypaimon import CatalogFactory, Schema
from pypaimon.globalindex.indexed_split import IndexedSplit
from pypaimon.utils.range import Range

CLICKBENCH_URL = "https://datasets.clickhouse.com/hits_compatible/hits.parquet"

# Formats to benchmark
FORMATS = ["parquet", "orc", "lance", "vortex"]


def download_clickbench(dest_path: str):
    """Download Clickbench hits.parquet if not already present."""
    if os.path.exists(dest_path):
        print(f"[INFO] Using cached dataset: {dest_path}")
        return
    print(f"[INFO] Downloading Clickbench dataset to {dest_path} ...")
    print(f"[INFO] URL: {CLICKBENCH_URL}")
    print("[INFO] This is ~14GB, may take a while.")

    import urllib.request
    urllib.request.urlretrieve(CLICKBENCH_URL, dest_path)
    print("[INFO] Download complete.")


def load_data(data_path: str, max_rows: int) -> pa.Table:
    """Load Clickbench parquet data, optionally limiting rows."""
    print(f"[INFO] Loading data from {data_path} ...")
    pf = pq.ParquetFile(data_path)
    if max_rows > 0:
        # Read enough row groups to satisfy max_rows
        batches = []
        total = 0
        for rg_idx in range(pf.metadata.num_row_groups):
            rg = pf.read_row_group(rg_idx)
            batches.append(rg)
            total += rg.num_rows
            if total >= max_rows:
                break
        table = pa.concat_tables(batches)
        if table.num_rows > max_rows:
            table = table.slice(0, max_rows)
    else:
        table = pf.read()

    # Cast unsigned integer types to signed (Paimon doesn't support unsigned)
    uint_to_int = {
        pa.uint8(): pa.int16(),
        pa.uint16(): pa.int32(),
        pa.uint32(): pa.int64(),
        pa.uint64(): pa.int64(),
    }
    new_fields = []
    for field in table.schema:
        if field.type in uint_to_int:
            new_fields.append((field.name, uint_to_int[field.type]))
    if new_fields:
        print(f"[INFO] Casting {len(new_fields)} unsigned int columns to signed")
        for name, target_type in new_fields:
            table = table.set_column(
                table.schema.get_field_index(name),
                pa.field(name, target_type, nullable=table.schema.field(name).nullable),
                table.column(name).cast(target_type),
            )

    print(f"[INFO] Loaded {table.num_rows:,} rows, {table.num_columns} columns")
    print(f"[INFO] In-memory size: {table.nbytes / 1024 / 1024:.1f} MB")
    return table


def get_dir_size(path: str) -> int:
    """Get total size of all files under a directory."""
    total = 0
    for dirpath, _, filenames in os.walk(path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            if os.path.isfile(fp):
                total += os.path.getsize(fp)
    return total


def write_paimon_table(catalog, table_name: str, pa_schema: pa.Schema,
                       data: pa.Table, file_format: str) -> dict:
    """Write data to a Paimon table and return metrics."""
    schema = Schema.from_pyarrow_schema(pa_schema, options={
        'file.format': file_format,
        'data-evolution.enabled': 'true',
        'row-tracking.enabled': 'true',
    })
    catalog.create_table(f'default.{table_name}', schema, False)
    table = catalog.get_table(f'default.{table_name}')

    write_builder = table.new_batch_write_builder()
    table_write = write_builder.new_write()
    table_commit = write_builder.new_commit()

    t0 = time.time()
    table_write.write_arrow(data)
    table_commit.commit(table_write.prepare_commit())
    write_time = time.time() - t0

    table_write.close()
    table_commit.close()

    return {
        'write_time': write_time,
    }


def read_paimon_table(catalog, table_name: str) -> dict:
    """Read all data from a Paimon table and return metrics."""
    table = catalog.get_table(f'default.{table_name}')
    read_builder = table.new_read_builder()
    table_scan = read_builder.new_scan()
    table_read = read_builder.new_read()

    t0 = time.time()
    result = table_read.to_arrow(table_scan.plan().splits())
    read_time = time.time() - t0

    return {
        'read_time': read_time,
        'num_rows': result.num_rows,
    }


def point_lookup_paimon_table(catalog, table_name: str, num_lookups: int, rows_per_lookup: int) -> dict:
    """Run row-ID-based point lookups on a data-evolution Paimon table."""
    table = catalog.get_table(f'default.{table_name}')
    read_builder = table.new_read_builder()
    scan = read_builder.new_scan()
    splits = scan.plan().splits()

    # Determine total row range from splits
    total_rows = sum(s.row_count for s in splits)

    # Generate random row ID ranges for lookups
    random.seed(42)
    lookup_ranges = []
    for _ in range(num_lookups):
        start = random.randint(0, total_rows - rows_per_lookup)
        lookup_ranges.append(Range(start, start + rows_per_lookup - 1))

    total_result_rows = 0
    t0 = time.time()
    for rng in lookup_ranges:
        indexed_splits = []
        for s in splits:
            # Intersect the lookup range with each split's file ranges
            file_ranges = []
            for f in s.files:
                if f.first_row_id is not None:
                    file_ranges.append(Range(f.first_row_id, f.first_row_id + f.row_count - 1))
            split_range = Range.and_([rng], file_ranges)
            if split_range:
                indexed_splits.append(IndexedSplit(s, [rng]))

        if indexed_splits:
            read = read_builder.new_read()
            result = read.to_arrow(indexed_splits)
            total_result_rows += result.num_rows

    lookup_time = time.time() - t0

    return {
        'lookup_time': lookup_time,
        'num_lookups': num_lookups,
        'total_rows': total_result_rows,
    }


def predicate_lookup_paimon_table(catalog, table_name: str, num_lookups: int, rows_per_lookup: int) -> dict:
    """Run predicate-based point lookups using _ROW_ID filter on a data-evolution Paimon table."""
    table = catalog.get_table(f'default.{table_name}')

    # Get total rows to generate random ranges
    rb = table.new_read_builder()
    splits = rb.new_scan().plan().splits()
    total_rows = sum(s.row_count for s in splits)

    # Build predicate builder with _ROW_ID in projection
    all_cols = [f.name for f in table.fields] + ['_ROW_ID']
    pb = table.new_read_builder().with_projection(all_cols).new_predicate_builder()

    random.seed(42)
    total_result_rows = 0
    t0 = time.time()
    for _ in range(num_lookups):
        start = random.randint(0, total_rows - rows_per_lookup)
        end = start + rows_per_lookup - 1
        pred = pb.between('_ROW_ID', start, end)
        filtered_rb = table.new_read_builder().with_filter(pred)
        scan = filtered_rb.new_scan()
        read = filtered_rb.new_read()
        result = read.to_arrow(scan.plan().splits())
        total_result_rows += result.num_rows

    lookup_time = time.time() - t0

    return {
        'lookup_time': lookup_time,
        'num_lookups': num_lookups,
        'total_rows': total_result_rows,
    }


def run_benchmark(data: pa.Table, warehouse_dir: str):
    """Run the compression benchmark across all formats."""
    catalog = CatalogFactory.create({'warehouse': warehouse_dir})
    catalog.create_database('default', True)

    pa_schema = data.schema
    in_memory_mb = data.nbytes / 1024 / 1024
    results = {}

    num_lookups = 20
    rows_per_lookup = 100

    for fmt in FORMATS:
        table_name = f"clickbench_{fmt}"
        print(f"\n{'='*60}")
        print(f"  Format: {fmt.upper()}")
        print(f"{'='*60}")

        # Write
        print(f"  Writing {data.num_rows:,} rows ...")
        write_metrics = write_paimon_table(catalog, table_name, pa_schema, data, fmt)
        print(f"  Write time: {write_metrics['write_time']:.2f}s")

        # Measure on-disk size
        table = catalog.get_table(f'default.{table_name}')
        table_path = table.table_path
        disk_size = get_dir_size(table_path)
        disk_mb = disk_size / 1024 / 1024
        ratio = in_memory_mb / disk_mb if disk_mb > 0 else 0
        print(f"  On-disk size: {disk_mb:.1f} MB  (ratio: {ratio:.2f}x)")

        # Full read
        print("  Reading back ...")
        read_metrics = read_paimon_table(catalog, table_name)
        print(f"  Read time: {read_metrics['read_time']:.2f}s")
        print(f"  Rows read: {read_metrics['num_rows']:,}")

        # Point lookups by row ID
        print(f"  Point lookups ({num_lookups} queries, {rows_per_lookup} rows each) ...")
        lookup_metrics = point_lookup_paimon_table(catalog, table_name, num_lookups, rows_per_lookup)
        print(f"  Lookup time: {lookup_metrics['lookup_time']:.2f}s")
        print(f"  Total rows matched: {lookup_metrics['total_rows']:,}")

        # Predicate-based point lookups by _ROW_ID
        print(f"  Predicate lookups ({num_lookups} queries, {rows_per_lookup} rows each) ...")
        pred_metrics = predicate_lookup_paimon_table(catalog, table_name, num_lookups, rows_per_lookup)
        print(f"  Predicate lookup time: {pred_metrics['lookup_time']:.2f}s")
        print(f"  Total rows matched: {pred_metrics['total_rows']:,}")

        results[fmt] = {
            'write_time': write_metrics['write_time'],
            'read_time': read_metrics['read_time'],
            'disk_mb': disk_mb,
            'ratio': ratio,
            'lookup_time': lookup_metrics['lookup_time'],
            'lookup_rows': lookup_metrics['total_rows'],
            'pred_lookup_time': pred_metrics['lookup_time'],
            'pred_lookup_rows': pred_metrics['total_rows'],
        }

    return results


def print_summary(results: dict, in_memory_mb: float, num_rows: int):
    """Print a summary comparison table."""
    print(f"\n{'='*80}")
    print("  CLICKBENCH COMPRESSION BENCHMARK SUMMARY")
    print(f"  Rows: {num_rows:,}  |  In-memory: {in_memory_mb:.1f} MB")
    print(f"{'='*80}")
    print(f"  {'Format':<10} {'Disk (MB)':>10} {'Ratio':>8} {'Write (s)':>10} "
          f"{'Read (s)':>10} {'Lookup (s)':>11} {'Pred (s)':>10}")
    print(f"  {'-'*69}")

    for fmt in FORMATS:
        if fmt in results:
            r = results[fmt]
            print(f"  {fmt:<10} {r['disk_mb']:>10.1f} {r['ratio']:>7.2f}x {r['write_time']:>10.2f} "
                  f"{r['read_time']:>10.2f} {r['lookup_time']:>11.2f} {r['pred_lookup_time']:>10.2f}")

    # Vortex vs Parquet comparison
    if 'vortex' in results and 'parquet' in results:
        v = results['vortex']
        p = results['parquet']
        print("\n  Vortex vs Parquet:")
        print(f"    Size:   {v['disk_mb'] / p['disk_mb'] * 100:.1f}% of Parquet")
        print(f"    Write:  {v['write_time'] / p['write_time']:.2f}x")
        print(f"    Read:   {v['read_time'] / p['read_time']:.2f}x")
        print(f"    Lookup: {v['lookup_time'] / p['lookup_time']:.2f}x")
        print(f"    Pred:   {v['pred_lookup_time'] / p['pred_lookup_time']:.2f}x")


def main():
    parser = argparse.ArgumentParser(description="Clickbench compression benchmark for Paimon")
    parser.add_argument("--rows", type=int, default=3_000_000,
                        help="Number of rows to use (0 = full dataset, default: 3000000)")
    parser.add_argument("--data-path", type=str, default=None,
                        help="Path to existing hits.parquet (skips download)")
    args = parser.parse_args()

    # Resolve data path
    if args.data_path:
        data_path = args.data_path
    else:
        cache_dir = os.path.join(Path.home(), ".cache", "paimon-bench")
        os.makedirs(cache_dir, exist_ok=True)
        data_path = os.path.join(cache_dir, "hits.parquet")
        download_clickbench(data_path)

    data = load_data(data_path, args.rows)
    in_memory_mb = data.nbytes / 1024 / 1024

    warehouse_dir = tempfile.mkdtemp(prefix="paimon_bench_")
    print(f"[INFO] Warehouse: {warehouse_dir}")

    try:
        results = run_benchmark(data, warehouse_dir)
        print_summary(results, in_memory_mb, data.num_rows)
    finally:
        shutil.rmtree(warehouse_dir, ignore_errors=True)


if __name__ == "__main__":
    main()
