# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.
# SPDX-License-Identifier: AGPL-3.0

"""AGFS Python Binding Tests for VikingFS interface with S3 backend

Tests the python binding mode of VikingFS with S3 backend (MinIO/TOS).
"""

import json
import os
import uuid
from pathlib import Path

import pytest

from openviking.storage.transaction import init_lock_manager, reset_lock_manager
from openviking.storage.viking_fs import init_viking_fs
from openviking_cli.utils.config import OPENVIKING_CONFIG_ENV
from openviking_cli.utils.config.agfs_config import AGFSConfig

CONFIG_FILE = os.getenv(OPENVIKING_CONFIG_ENV)
if not CONFIG_FILE:
    default_conf = Path(__file__).parent / "ov.conf"
    if default_conf.exists():
        CONFIG_FILE = str(default_conf)


def load_agfs_config() -> AGFSConfig:
    """Load only AGFS configuration from the config file."""
    if not CONFIG_FILE or not Path(CONFIG_FILE).exists():
        return None

    try:
        with open(CONFIG_FILE, "r") as f:
            full_config = json.load(f)

        agfs_data = full_config.get("storage", {}).get("agfs") or full_config.get("agfs")
        if not agfs_data:
            return None

        return AGFSConfig(**agfs_data)
    except Exception:
        return None


AGFS_CONF = load_agfs_config()

pytestmark = pytest.mark.skipif(
    AGFS_CONF is None or AGFS_CONF.backend != "s3",
    reason="AGFS binding client install failed or S3 configuration not available",
)


@pytest.fixture(scope="module")
async def viking_fs_binding_s3_instance():
    """Initialize VikingFS with binding mode for S3 backend."""
    from openviking.utils.agfs_utils import RagfsBindingConfig, create_agfs_client

    # Create AGFS client
    agfs_client = create_agfs_client(RagfsBindingConfig(agfs=AGFS_CONF))

    # Initialize LockManager and VikingFS with client
    init_lock_manager(agfs=agfs_client)
    vfs = init_viking_fs(agfs=agfs_client)

    yield vfs

    reset_lock_manager()


@pytest.mark.asyncio
class TestVikingFSBindingS3:
    """Test VikingFS operations with binding mode (S3 backend)."""

    async def test_s3_file_operations(self, viking_fs_binding_s3_instance):
        """Test VikingFS file operations on S3: read, write, ls, stat."""
        vfs = viking_fs_binding_s3_instance
        test_filename = f"s3_binding_file_{uuid.uuid4().hex}.txt"
        test_content = "Hello VikingFS S3 Binding! " + uuid.uuid4().hex
        test_uri = f"viking://temp/{test_filename}"

        await vfs.write(test_uri, test_content)

        stat_info = await vfs.stat(test_uri)
        assert stat_info["name"] == test_filename
        assert not stat_info["isDir"]

        entries = await vfs.ls("viking://temp/")
        assert any(e["name"] == test_filename for e in entries)

        read_data = await vfs.read(test_uri)
        assert read_data.decode("utf-8") == test_content

        await vfs.rm(test_uri)

    async def test_s3_directory_operations(self, viking_fs_binding_s3_instance):
        """Test VikingFS directory operations on S3: mkdir, rm, ls, stat."""
        vfs = viking_fs_binding_s3_instance
        test_dir = f"s3_binding_dir_{uuid.uuid4().hex}"
        test_dir_uri = f"viking://temp/{test_dir}/"

        await vfs.mkdir(test_dir_uri)

        stat_info = await vfs.stat(test_dir_uri)
        assert stat_info["name"] == test_dir
        assert stat_info["isDir"]

        root_entries = await vfs.ls("viking://temp/")
        assert any(e["name"] == test_dir and e["isDir"] for e in root_entries)

        file_uri = f"{test_dir_uri}inner.txt"
        await vfs.write(file_uri, "inner content for S3")

        sub_entries = await vfs.ls(test_dir_uri)
        assert any(e["name"] == "inner.txt" for e in sub_entries)

        await vfs.rm(test_dir_uri, recursive=True)

        root_entries = await vfs.ls("viking://temp/")
        assert not any(e["name"] == test_dir for e in root_entries)

    async def test_s3_tree_operations(self, viking_fs_binding_s3_instance):
        """Test VikingFS tree operations on S3."""
        vfs = viking_fs_binding_s3_instance
        base_dir = f"s3_binding_tree_{uuid.uuid4().hex}"
        sub_dir = f"viking://temp/{base_dir}/a/b/"
        file_uri = f"{sub_dir}leaf.txt"

        await vfs.mkdir(sub_dir)
        await vfs.write(file_uri, "leaf content in S3")

        entries = await vfs.tree(f"viking://temp/{base_dir}/")
        assert any("leaf.txt" in e["uri"] for e in entries)

        await vfs.rm(f"viking://temp/{base_dir}/", recursive=True)

    async def test_s3_binary_operations(self, viking_fs_binding_s3_instance):
        """Test VikingFS binary file operations on S3."""
        vfs = viking_fs_binding_s3_instance
        test_filename = f"s3_binding_binary_{uuid.uuid4().hex}.bin"
        test_content = bytes([i % 256 for i in range(256)])
        test_uri = f"viking://temp/{test_filename}"

        await vfs.write(test_uri, test_content)

        read_data = await vfs.read(test_uri)
        assert read_data == test_content

        await vfs.rm(test_uri)
