#!/usr/bin/env python3
"""
真实 MinIO 连接测试

测试与本地 MinIO 实例的真实连接和上传功能
"""

import sys
import os
import tempfile
import asyncio
from pathlib import Path

# Add the parent directory to the path to import sandai
sys.path.insert(0, str(Path(__file__).parent.parent))

from sandai.operator.processor import BatchProcessor
from sandai.operator.env import get_minio_config


def test_minio_connection():
    """测试 MinIO 连接"""
    print("🧪 测试 MinIO 连接")
    
    # 获取 MinIO 配置
    config = get_minio_config()
    
    print(f"   连接信息:")
    print(f"   - Endpoint: {config.endpoint}")
    print(f"   - Bucket: {config.bucket_name}")
    print(f"   - Access Key: {config.access_key}")
    print(f"   - Secure: {config.secure}")
    
    try:
        import boto3
        from botocore.exceptions import ClientError, NoCredentialsError, EndpointConnectionError
        
        # 创建 S3 客户端
        s3_client = boto3.client(
            's3',
            endpoint_url=f"{'https' if config.secure else 'http'}://{config.endpoint}",
            aws_access_key_id=config.access_key,
            aws_secret_access_key=config.secret_key,
            region_name=config.region
        )
        
        # 测试连接 - 列出 buckets
        response = s3_client.list_buckets()
        buckets = [bucket['Name'] for bucket in response['Buckets']]
        
        print(f"   ✅ 连接成功!")
        print(f"   📦 现有 buckets: {buckets}")
        
        # 检查目标 bucket 是否存在
        if config.bucket_name in buckets:
            print(f"   ✅ 目标 bucket '{config.bucket_name}' 已存在")
        else:
            print(f"   ⚠️  目标 bucket '{config.bucket_name}' 不存在，将自动创建")
        
        return True
        
    except EndpointConnectionError as e:
        print(f"   ❌ 连接失败: 无法连接到 {config.endpoint}")
        print(f"      请确保 MinIO 服务正在运行")
        return False
    except NoCredentialsError as e:
        print(f"   ❌ 认证失败: 凭据无效")
        return False
    except Exception as e:
        print(f"   ❌ 连接失败: {e}")
        return False


def test_minio_real_upload():
    """测试真实的 MinIO 上传"""
    print("\n🧪 测试真实 MinIO 上传")
    
    # 创建 processor
    processor = BatchProcessor("test-operator", "v1", ignore_nongil_check=True)
    processor._setup_temp_directory()
    
    # 创建测试文件
    import time
    test_content = f"Test file for MinIO upload\nTimestamp: {time.time()}\nContent: Hello MinIO!"
    
    with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
        f.write(test_content)
        test_file_path = f.name
    
    try:
        print(f"   📄 测试文件: {test_file_path}")
        print(f"   📝 文件内容: {len(test_content)} 字符")
        
        # 运行上传测试
        async def run_upload_test():
            url = await processor._upload_to_storage(test_file_path)
            return url
        
        # 执行异步测试
        result_url = asyncio.run(run_upload_test())
        
        print(f"   ✅ 上传成功!")
        print(f"   🔗 文件 URL: {result_url}")
        
        # 验证 URL 格式
        config = get_minio_config()
        expected_prefix = f"{'https' if config.secure else 'http'}://{config.endpoint}/{config.bucket_name}/{config.prefix}/"
        
        if result_url.startswith(expected_prefix):
            print(f"   ✅ URL 格式正确")
        else:
            print(f"   ⚠️  URL 格式异常")
            print(f"      期望前缀: {expected_prefix}")
            print(f"      实际 URL: {result_url}")
        
        return True
        
    except Exception as e:
        print(f"   ❌ 上传失败: {e}")
        import traceback
        traceback.print_exc()
        return False
        
    finally:
        # 清理测试文件
        if os.path.exists(test_file_path):
            os.unlink(test_file_path)
            print(f"   🧹 已清理本地测试文件")


def test_minio_bucket_operations():
    """测试 MinIO bucket 操作"""
    print("\n🧪 测试 MinIO bucket 操作")
    
    try:
        import boto3
        from botocore.exceptions import ClientError
        
        config = get_minio_config()
        
        # 创建 S3 客户端
        s3_client = boto3.client(
            's3',
            endpoint_url=f"{'https' if config.secure else 'http'}://{config.endpoint}",
            aws_access_key_id=config.access_key,
            aws_secret_access_key=config.secret_key,
            region_name=config.region
        )
        
        # 检查 bucket 是否存在
        try:
            s3_client.head_bucket(Bucket=config.bucket_name)
            print(f"   ✅ Bucket '{config.bucket_name}' 存在")
            bucket_exists = True
        except ClientError as e:
            if e.response['Error']['Code'] == '404':
                print(f"   ⚠️  Bucket '{config.bucket_name}' 不存在")
                bucket_exists = False
            else:
                raise
        
        # 如果 bucket 不存在，创建它
        if not bucket_exists:
            print(f"   🔨 创建 bucket '{config.bucket_name}'...")
            s3_client.create_bucket(Bucket=config.bucket_name)
            print(f"   ✅ Bucket 创建成功!")
        
        # 列出 bucket 中的对象
        try:
            response = s3_client.list_objects_v2(
                Bucket=config.bucket_name,
                Prefix=config.prefix,
                MaxKeys=10
            )
            
            if 'Contents' in response:
                objects = response['Contents']
                print(f"   📦 Bucket 中有 {len(objects)} 个对象 (前10个):")
                for obj in objects[:5]:  # 只显示前5个
                    print(f"      - {obj['Key']} ({obj['Size']} bytes)")
                if len(objects) > 5:
                    print(f"      ... 还有 {len(objects) - 5} 个对象")
            else:
                print(f"   📦 Bucket 为空")
                
        except Exception as e:
            print(f"   ⚠️  无法列出对象: {e}")
        
        return True
        
    except Exception as e:
        print(f"   ❌ Bucket 操作失败: {e}")
        return False


def test_minio_with_custom_config():
    """测试自定义 MinIO 配置"""
    print("\n🧪 测试自定义 MinIO 配置")
    
    # 使用环境变量覆盖配置
    original_env = {}
    custom_env = {
        "SANDAI_OPERATOR_MINIO_BUCKET": "test-sandai-bucket",
        "SANDAI_OPERATOR_MINIO_PREFIX": "test-uploads"
    }
    
    # 保存原始环境变量
    for key in custom_env:
        if key in os.environ:
            original_env[key] = os.environ[key]
    
    try:
        # 设置自定义环境变量
        for key, value in custom_env.items():
            os.environ[key] = value
        
        # 重新获取配置
        from importlib import reload
        from sandai.operator import env
        reload(env)
        
        config = env.get_minio_config()
        
        print(f"   📝 自定义配置:")
        print(f"      Bucket: {config.bucket_name}")
        print(f"      Prefix: {config.prefix}")
        
        # 创建 processor 并测试上传
        processor = BatchProcessor("test-operator", "v1", ignore_nongil_check=True)
        processor._setup_temp_directory()
        
        # 创建测试文件
        with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
            f.write("Test content for custom config")
            test_file_path = f.name
        
        try:
            # 运行上传测试
            async def run_upload_test():
                url = await processor._upload_to_storage(test_file_path)
                return url
            
            result_url = asyncio.run(run_upload_test())
            
            # 验证 URL 包含自定义配置
            if config.bucket_name in result_url and config.prefix in result_url:
                print(f"   ✅ 自定义配置生效!")
                print(f"   🔗 上传 URL: {result_url}")
                return True
            else:
                print(f"   ❌ 自定义配置未生效")
                print(f"   🔗 实际 URL: {result_url}")
                return False
                
        finally:
            # 清理测试文件
            if os.path.exists(test_file_path):
                os.unlink(test_file_path)
        
    finally:
        # 恢复原始环境变量
        for key in custom_env:
            if key in original_env:
                os.environ[key] = original_env[key]
            else:
                os.environ.pop(key, None)
        
        # 重新加载配置
        reload(env)


def run_real_minio_tests():
    """运行真实 MinIO 测试"""
    print("🚀 开始真实 MinIO 测试")
    print("=" * 60)
    print("⚠️  注意: 此测试需要本地 MinIO 服务运行在 localhost:9000")
    print("   启动命令: docker run -p 9000:9000 -p 9001:9001 minio/minio server /data --console-address \":9001\"")
    print("=" * 60)
    
    tests = [
        ("MinIO 连接测试", test_minio_connection),
        ("MinIO 真实上传测试", test_minio_real_upload),
        ("MinIO Bucket 操作测试", test_minio_bucket_operations),
        ("MinIO 自定义配置测试", test_minio_with_custom_config),
    ]
    
    passed = 0
    failed = 0
    
    for test_name, test_func in tests:
        print(f"\n{'='*20} {test_name} {'='*20}")
        try:
            if test_func():
                passed += 1
                print(f"✅ {test_name} - 通过")
            else:
                failed += 1
                print(f"❌ {test_name} - 失败")
        except Exception as e:
            failed += 1
            print(f"❌ {test_name} - 异常: {e}")
            import traceback
            traceback.print_exc()
    
    print("\n" + "=" * 60)
    print(f"📊 测试结果: {passed} 通过, {failed} 失败")
    
    if failed == 0:
        print("🎉 所有真实 MinIO 测试通过!")
        print("\n📋 验证功能:")
        print("   ✅ MinIO 服务连接")
        print("   ✅ 真实文件上传")
        print("   ✅ Bucket 自动创建")
        print("   ✅ 对象列表查询")
        print("   ✅ 自定义配置支持")
        return True
    else:
        print("💥 部分测试失败")
        if failed == len(tests):
            print("🔧 可能的问题:")
            print("   - MinIO 服务未启动")
            print("   - 端口 9000 被占用")
            print("   - 网络连接问题")
            print("   - 认证凭据错误")
        return False


if __name__ == '__main__':
    success = run_real_minio_tests()
    sys.exit(0 if success else 1)