#!/usr/bin/env python3
#exonware/xwsystem/tests/1.unit/serialization_tests/test_new_serializers.py
"""
Test script for new schema-based serialization formats in xSystem.
"""

import sys
import traceback
from pathlib import Path
# Add src to path - adjusted for new location
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))

def test_avro():
    """Test Apache Avro serialization."""
    print("🔸 Testing Apache Avro...")
    try:
        from exonware.xwsystem.serialization.avro import AvroSerializer
        # Simple schema for testing
        schema = {
            "type": "record",
            "name": "TestRecord",
            "fields": [
                {"name": "name", "type": "string"},
                {"name": "age", "type": "int"},
                {"name": "active", "type": "boolean"}
            ]
        }
        serializer = AvroSerializer(schema=schema)
        test_data = {"name": "John Doe", "age": 30, "active": True}
        # Test serialization
        serialized = serializer.dumps(test_data)
        print(f"  ✅ Serialized: {len(serialized)} chars")
        # Test deserialization
        deserialized = serializer.loads(serialized)
        print(f"  ✅ Deserialized: {deserialized}")
        assert deserialized["name"] == test_data["name"]
        assert deserialized["age"] == test_data["age"]
        assert deserialized["active"] == test_data["active"]
        print("  ✅ Avro test PASSED")
        return True
    except ImportError as e:
        print(f"  ⚠️  Avro test SKIPPED (missing dependency): {e}")
        return True
    except Exception as e:
        print(f"  ❌ Avro test FAILED: {e}")
        traceback.print_exc()
        return False


def test_protobuf():
    """Test Protocol Buffers serialization."""
    print("🔸 Testing Protocol Buffers...")
    try:
        from exonware.xwsystem.serialization.protobuf import ProtobufSerializer
        # Create a simple protobuf message class for testing
        try:
            from google.protobuf import descriptor_pb2
            from google.protobuf.message import Message
            # For testing, we'll use a simple dict-based approach
            # In real usage, you'd have generated protobuf classes
            print("  ⚠️  Protobuf test requires generated message classes - testing basic functionality")
            # Test without message type (should fail gracefully)
            serializer = ProtobufSerializer()
            try:
                serializer.dumps({"test": "data"})
                print("  ❌ Should have failed without message type")
                return False
            except Exception:
                print("  ✅ Correctly failed without message type")
        except ImportError:
            print("  ⚠️  Protobuf library not available")
        print("  ✅ Protobuf test PASSED (basic validation)")
        return True
    except ImportError as e:
        print(f"  ⚠️  Protobuf test SKIPPED (missing dependency): {e}")
        return True
    except Exception as e:
        print(f"  ❌ Protobuf test FAILED: {e}")
        return False


def test_parquet():
    """Test Apache Parquet serialization."""
    print("🔸 Testing Apache Parquet...")
    try:
        from exonware.xwsystem.serialization.parquet import ParquetSerializer
        serializer = ParquetSerializer()
        # Test with list of dictionaries (typical use case)
        test_data = [
            {"name": "Alice", "age": 25, "city": "NYC"},
            {"name": "Bob", "age": 30, "city": "LA"},
            {"name": "Charlie", "age": 35, "city": "Chicago"}
        ]
        # Test serialization
        serialized = serializer.dumps(test_data)
        print(f"  ✅ Serialized: {len(serialized)} chars")
        # Test deserialization
        deserialized = serializer.loads(serialized)
        print(f"  ✅ Deserialized: {len(deserialized)} records")
        assert len(deserialized) == 3
        assert deserialized[0]["name"] == "Alice"
        assert deserialized[1]["age"] == 30
        # Test single dict
        single_data = {"name": "Single", "value": 42}
        serialized_single = serializer.dumps(single_data)
        deserialized_single = serializer.loads(serialized_single)
        print(f"  ✅ Single record: {deserialized_single}")
        print("  ✅ Parquet test PASSED")
        return True
    except ImportError as e:
        print(f"  ⚠️  Parquet test SKIPPED (missing dependency): {e}")
        return True
    except Exception as e:
        print(f"  ❌ Parquet test FAILED: {e}")
        traceback.print_exc()
        return False


def test_thrift():
    """Test Apache Thrift serialization."""
    print("🔸 Testing Apache Thrift...")
    try:
        from exonware.xwsystem.serialization.thrift import ThriftSerializer
        # Test JSON protocol (doesn't require generated classes)
        serializer = ThriftSerializer(protocol="json")
        print("  ⚠️  Thrift test requires generated thrift classes - testing basic functionality")
        # Test validation
        try:
            serializer.dumps({"test": "data"})
            print("  ❌ Should have failed without thrift class")
            return False
        except Exception:
            print("  ✅ Correctly failed without thrift class")
        print("  ✅ Thrift test PASSED (basic validation)")
        return True
    except ImportError as e:
        print(f"  ⚠️  Thrift test SKIPPED (missing dependency): {e}")
        return True
    except Exception as e:
        print(f"  ❌ Thrift test FAILED: {e}")
        return False


def test_orc():
    """Test Apache ORC serialization."""
    print("🔸 Testing Apache ORC...")
    try:
        from exonware.xwsystem.serialization.orc import OrcSerializer
        serializer = OrcSerializer()
        # Test with list of dictionaries
        test_data = [
            {"name": "Alice", "age": 25, "salary": 50000.0},
            {"name": "Bob", "age": 30, "salary": 60000.0}
        ]
        # Test serialization
        serialized = serializer.dumps(test_data)
        print(f"  ✅ Serialized: {len(serialized)} chars")
        # Test deserialization
        deserialized = serializer.loads(serialized)
        print(f"  ✅ Deserialized: {deserialized}")
        assert len(deserialized) == 2
        assert deserialized[0]["name"] == "Alice"
        print("  ✅ ORC test PASSED")
        return True
    except ImportError as e:
        print(f"  ⚠️  ORC test SKIPPED (missing dependency): {e}")
        return True
    except Exception as e:
        print(f"  ❌ ORC test FAILED: {e}")
        traceback.print_exc()
        return False


def test_capnproto():
    """Test Cap'n Proto serialization."""
    print("🔸 Testing Cap'n Proto...")
    try:
        from exonware.xwsystem.serialization.capnproto import CapnProtoSerializer
        print("  ⚠️  Cap'n Proto requires schema files - testing basic functionality")
        # Test validation
        serializer = CapnProtoSerializer()
        try:
            serializer.dumps({"test": "data"})
            print("  ❌ Should have failed without schema")
            return False
        except Exception:
            print("  ✅ Correctly failed without schema")
        print("  ✅ Cap'n Proto test PASSED (basic validation)")
        return True
    except ImportError as e:
        print(f"  ⚠️  Cap'n Proto test SKIPPED (missing dependency): {e}")
        return True
    except Exception as e:
        print(f"  ❌ Cap'n Proto test FAILED: {e}")
        return False


def test_flatbuffers():
    """Test FlatBuffers serialization."""
    print("🔸 Testing FlatBuffers...")
    try:
        from exonware.xwsystem.serialization.flatbuffers import FlatBuffersSerializer
        serializer = FlatBuffersSerializer()
        # Test with simple data (uses generic implementation)
        test_data = {"name": "Test", "value": 123}
        # Test serialization (will use JSON fallback)
        serialized = serializer.dumps(test_data)
        print(f"  ✅ Serialized: {len(serialized)} chars")
        # Test deserialization
        deserialized = serializer.loads(serialized)
        print(f"  ✅ Deserialized: {deserialized}")
        assert deserialized["name"] == test_data["name"]
        assert deserialized["value"] == test_data["value"]
        print("  ✅ FlatBuffers test PASSED (generic mode)")
        return True
    except ImportError as e:
        print(f"  ⚠️  FlatBuffers test SKIPPED (missing dependency): {e}")
        return True
    except Exception as e:
        print(f"  ❌ FlatBuffers test FAILED: {e}")
        traceback.print_exc()
        return False


def test_import_all():
    """Test that all serializers can be imported from main package."""
    print("🔸 Testing imports from main package...")
    try:
        from exonware.xwsystem.serialization import (
            AvroSerializer, ProtobufSerializer, ThriftSerializer,
            ParquetSerializer, OrcSerializer, CapnProtoSerializer,
            FlatBuffersSerializer
        )
        print("  ✅ All serializers imported successfully")
        return True
    except ImportError as e:
        print(f"  ❌ Import test FAILED: {e}")
        return False


def main():
    """Run all tests."""
    print("🚀 Testing xSystem Schema-Based Serialization Formats")
    print("=" * 60)
    tests = [
        test_import_all,
        test_avro,
        test_protobuf,
        test_parquet,
        test_thrift,
        test_orc,
        test_capnproto,
        test_flatbuffers,
    ]
    passed = 0
    total = len(tests)
    for test in tests:
        try:
            if test():
                passed += 1
        except Exception as e:
            print(f"  ❌ {test.__name__} CRASHED: {e}")
        print()
    print("=" * 60)
    print(f"🎯 Results: {passed}/{total} tests passed")
    if passed == total:
        print("🎉 All tests PASSED! Schema-based serializers are working correctly.")
        return 0
    else:
        print("⚠️  Some tests failed or were skipped due to missing dependencies.")
        print("   Install missing packages: pip install fastavro protobuf thrift pyarrow pyorc pycapnp flatbuffers")
        return 1
if __name__ == "__main__":
    sys.exit(main())
