"""
VibeDB Schema Validation Test

Demonstrates schema-later approach with gradual validation.
"""

from vibedb import VibeDB
from vibedb.errors import ValidationError


def main():
    print("📋 VibeDB Schema Validation Test\n")

    db = VibeDB(":memory:")
    users = db.collection("users")

    # Test 1: Start schema-less
    print("✅ Test 1: Schema-less Insert (Anything Goes)")
    users.insert({"name": "Alice", "age": 28})
    users.insert({"username": "bob123"})  # Different structure - OK!
    users.insert({"x": 1, "y": 2, "z": 3})  # Anything goes!
    print(f"  ✓ Inserted {users.count()} documents with different structures\n")

    # Test 2: Add schema for new inserts
    print("📝 Test 2: Set Schema")
    schema = {
        "name": {
            "type": "string",
            "required": True,
            "min": 1,
            "max": 100
        },
        "age": {
            "type": "integer",
            "min": 0,
            "max": 150,
            "required": True
        },
        "email": {
            "type": "string",
            "required": True,
            "unique": True
        },
        "status": {
            "type": "string",
            "enum": ["active", "inactive", "pending"],
            "default": "active"
        },
        "tags": {
            "type": "array",
            "items": {"type": "string"}
        }
    }

    users.drop_schema()  # Clear old data first
    users.delete_many({})  # Start fresh

    users.set_schema(schema)
    print("  ✓ Schema set successfully\n")

    # Test 3: Valid inserts
    print("✅ Test 3: Valid Inserts")
    try:
        user1 = users.insert({
            "name": "Alice",
            "age": 28,
            "email": "alice@example.com",
            "tags": ["python", "ml"]
        })
        print(f"  ✓ Inserted user: {user1}")

        user2 = users.insert({
            "name": "Bob",
            "age": 35,
            "email": "bob@example.com",
            "status": "pending"
        })
        print(f"  ✓ Inserted user: {user2}")

        # Default value should be applied
        user = users.get(user1)
        print(f"  ✓ Status default applied: {user.status}\n")

    except ValidationError as e:
        print(f"  ✗ Unexpected error: {e.explain()}\n")

    # Test 4: Type validation
    print("❌ Test 4: Type Validation (Should Fail)")
    try:
        users.insert({
            "name": "Charlie",
            "age": "twenty-eight",  # Wrong type!
            "email": "charlie@example.com"
        })
        print("  ✗ Should have failed!\n")
    except ValidationError as e:
        print(f"  ✓ Caught type error:")
        print(f"    {e.explain()}\n")

    # Test 5: Required field validation
    print("❌ Test 5: Required Field (Should Fail)")
    try:
        users.insert({
            "name": "Diana",
            # Missing required 'age' and 'email'
        })
        print("  ✗ Should have failed!\n")
    except ValidationError as e:
        print(f"  ✓ Caught required field error:")
        print(f"    {e}\n")

    # Test 6: Min/Max constraints
    print("❌ Test 6: Min/Max Constraints (Should Fail)")
    try:
        users.insert({
            "name": "Eve",
            "age": -5,  # Below min!
            "email": "eve@example.com"
        })
        print("  ✗ Should have failed!\n")
    except ValidationError as e:
        print(f"  ✓ Caught min constraint error:")
        print(f"    {e}\n")

    try:
        users.insert({
            "name": "Frank",
            "age": 200,  # Above max!
            "email": "frank@example.com"
        })
        print("  ✗ Should have failed!\n")
    except ValidationError as e:
        print(f"  ✓ Caught max constraint error:")
        print(f"    {e}\n")

    # Test 7: Enum validation
    print("❌ Test 7: Enum Validation (Should Fail)")
    try:
        users.insert({
            "name": "Grace",
            "age": 30,
            "email": "grace@example.com",
            "status": "archived"  # Not in enum!
        })
        print("  ✗ Should have failed!\n")
    except ValidationError as e:
        print(f"  ✓ Caught enum error:")
        print(f"    {e}\n")

    # Test 8: Array items validation
    print("❌ Test 8: Array Items Validation (Should Fail)")
    try:
        users.insert({
            "name": "Henry",
            "age": 25,
            "email": "henry@example.com",
            "tags": ["python", 123, "ml"]  # Contains non-string!
        })
        print("  ✗ Should have failed!\n")
    except ValidationError as e:
        print(f"  ✓ Caught array item type error:")
        print(f"    {e}\n")

    # Test 9: Update with validation
    print("✅ Test 9: Update with Validation")
    try:
        users.update(user1, {"age": 29})
        print("  ✓ Valid update succeeded")

        users.update(user1, {"age": -1})
        print("  ✗ Invalid update should have failed!\n")
    except ValidationError as e:
        print(f"  ✓ Caught invalid update:")
        print(f"    {e}\n")

    # Test 10: Get and view schema
    print("📖 Test 10: Get Schema")
    current_schema = users.get_schema()
    print("  Current schema fields:")
    for field, constraints in current_schema.items():
        print(f"    • {field}: {constraints}")
    print()

    # Test 11: Drop schema
    print("🗑️  Test 11: Drop Schema")
    users.drop_schema()
    print("  ✓ Schema dropped")

    # Now anything goes again
    try:
        users.insert({"random": "data", "x": 123})
        print("  ✓ Schema-less insert works again\n")
    except ValidationError:
        print("  ✗ Should have allowed any structure!\n")

    db.close()
    print("✅ All schema validation tests completed!")


if __name__ == "__main__":
    main()
