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

"""End-to-end tests for Paimon system tables via pypaimon SQL.

Exercises the `<table>$<system_name>` syntax handled by paimon-rust
DataFusion integration. A non-partitioned table with one snapshot is
created in setUpClass and queried by each test.
"""

import json
import os
import tempfile
import unittest

import pyarrow as pa

from pypaimon_rust.datafusion import SQLContext


WAREHOUSE = os.environ.get("PAIMON_TEST_WAREHOUSE")
TABLE_NAME = "sql_system_test_table"
ROW_COUNT = 3


class SQLSystemTableTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls._tmpdir = None
        if WAREHOUSE:
            cls.warehouse = WAREHOUSE
        else:
            cls._tmpdir = tempfile.TemporaryDirectory(prefix="paimon-sql-systest-")
            cls.warehouse = cls._tmpdir.name

        ctx = SQLContext()
        ctx.register_catalog("paimon", {"warehouse": cls.warehouse})
        ctx.sql(f"DROP TABLE IF EXISTS {TABLE_NAME}")
        ctx.sql(f"CREATE TABLE {TABLE_NAME} (id INT, name STRING)")
        ctx.sql(
            f"INSERT INTO {TABLE_NAME} VALUES (1, 'alice'), (2, 'bob'), (3, 'carol')"
        )
        cls.ctx = ctx

    @classmethod
    def tearDownClass(cls):
        ctx = SQLContext()
        ctx.register_catalog("paimon", {"warehouse": cls.warehouse})
        ctx.sql(f"DROP TABLE IF EXISTS {TABLE_NAME}")
        if cls._tmpdir is not None:
            cls._tmpdir.cleanup()

    def _query(self, system_name: str) -> pa.Table:
        batches = self.ctx.sql(f"SELECT * FROM {TABLE_NAME}${system_name}")
        return pa.Table.from_batches(batches)

    def test_options_system_table(self):
        table = self._query("options")
        self.assertListEqual(table.schema.names, ["key", "value"])

    def test_schemas_system_table(self):
        table = self._query("schemas")
        self.assertListEqual(
            table.schema.names,
            ["schema_id", "fields", "partition_keys", "primary_keys",
             "options", "comment", "update_time"],
        )
        self.assertGreaterEqual(table.num_rows, 1, "should have at least one schema")
        ids = table.column("schema_id").to_pylist()
        self.assertEqual(sorted(ids), sorted(set(ids)), "schema_id should be unique")
        fields = json.loads(table.column("fields").to_pylist()[0])
        self.assertEqual([f["name"] for f in fields], ["id", "name"])

    def test_snapshots_system_table(self):
        table = self._query("snapshots")
        names = table.schema.names
        for required in (
            "snapshot_id", "schema_id", "commit_user", "commit_identifier",
            "commit_kind", "commit_time", "base_manifest_list",
            "delta_manifest_list", "total_record_count",
        ):
            self.assertIn(required, names)
        self.assertEqual(table.num_rows, 1, "single batch write should produce one snapshot")
        self.assertEqual(table.column("total_record_count").to_pylist()[0], ROW_COUNT)

    def test_tags_system_table_empty(self):
        table = self._query("tags")
        self.assertListEqual(
            table.schema.names,
            ["tag_name", "snapshot_id", "schema_id", "commit_time",
             "record_count", "create_time", "time_retained"],
        )
        self.assertEqual(table.num_rows, 0, "no tags created")

    def test_branches_system_table_empty(self):
        table = self._query("branches")
        self.assertListEqual(table.schema.names, ["branch_name", "create_time"])
        non_main = [b for b in table.column("branch_name").to_pylist() if b != "main"]
        self.assertEqual(non_main, [], "no user-created branches")

    def test_manifests_system_table(self):
        table = self._query("manifests")
        for required in (
            "file_name", "file_size", "num_added_files",
            "num_deleted_files", "schema_id",
        ):
            self.assertIn(required, table.schema.names)
        self.assertGreaterEqual(table.num_rows, 1, "snapshot should have manifests")
        for size in table.column("file_size").to_pylist():
            self.assertGreater(size, 0)
        total_added = sum(table.column("num_added_files").to_pylist())
        self.assertGreaterEqual(total_added, 1, "single write should add at least one file")


if __name__ == "__main__":
    unittest.main()
