"""Tests for DATAVOXEL ORM. Author: Juste Elysée MALANDILA"""
import pytest
import asyncio
from datavoxel import Model, Query


class User(Model):
    """Test user model."""
    __table__ = "users"


def test_model_creation():
    """Test creating a model instance."""
    user = User(name="John", email="john@example.com", age=30)
    
    assert user.name == "John"
    assert user.email == "john@example.com"
    assert user.age == 30
    assert user.id is None  # Not saved yet


def test_model_save_sync():
    """Test saving a model (sync)."""
    User._instances.clear()  # Reset
    User._next_id = 1
    
    user = User(name="Alice", email="alice@example.com")
    saved = user.save_sync()
    
    assert saved.id == 1
    assert User._instances[1] == saved


def test_model_get_sync():
    """Test getting a model by ID (sync)."""
    User._instances.clear()
    User._next_id = 1
    
    user = User(name="Bob", email="bob@example.com")
    user.save_sync()
    
    found = User.get_sync(id=1)
    assert found is not None
    assert found.name == "Bob"


def test_model_filter_sync():
    """Test filtering models (sync)."""
    User._instances.clear()
    User._next_id = 1
    
    User(name="Alice", email="alice@example.com", age=25).save_sync()
    User(name="Bob", email="bob@example.com", age=30).save_sync()
    User(name="Charlie", email="charlie@example.com", age=25).save_sync()
    
    # Filter by age
    users = User.filter_sync(age=25)
    assert len(users) == 2
    
    names = [u.name for u in users]
    assert "Alice" in names
    assert "Charlie" in names


def test_model_all_sync():
    """Test getting all models (sync)."""
    User._instances.clear()
    User._next_id = 1
    
    User(name="User1").save_sync()
    User(name="User2").save_sync()
    User(name="User3").save_sync()
    
    all_users = User.all_sync()
    assert len(all_users) == 3


def test_model_count_sync():
    """Test counting models (sync)."""
    User._instances.clear()
    User._next_id = 1
    
    assert User.count_sync() == 0
    
    User(name="User1").save_sync()
    assert User.count_sync() == 1
    
    User(name="User2").save_sync()
    assert User.count_sync() == 2


def test_model_delete_sync():
    """Test deleting a model (sync)."""
    User._instances.clear()
    User._next_id = 1
    
    user = User(name="ToDelete")
    user.save_sync()
    
    assert User.count_sync() == 1
    
    user.delete_sync()
    assert User.count_sync() == 0


def test_model_update():
    """Test updating a model."""
    User._instances.clear()
    User._next_id = 1
    
    user = User(name="Original", email="old@example.com")
    user.save_sync()
    
    # Update
    user.name = "Updated"
    user.email = "new@example.com"
    user.save_sync()
    
    # Verify update
    found = User.get_sync(id=user.id)
    assert found.name == "Updated"
    assert found.email == "new@example.com"


def test_model_dict():
    """Test converting model to dict."""
    User._instances.clear()
    User._next_id = 1
    
    user = User(name="John", email="john@example.com", age=30)
    user.save_sync()
    
    data = user.dict()
    assert data["name"] == "John"
    assert data["email"] == "john@example.com"
    assert data["age"] == 30
    assert data["id"] == 1


def test_query_where():
    """Test Query.where()."""
    User._instances.clear()
    User._next_id = 1
    
    User(name="Alice", age=25).save_sync()
    User(name="Bob", age=30).save_sync()
    User(name="Charlie", age=25).save_sync()
    
    results = Query(User).where(age=25).all_sync()
    assert len(results) == 2


def test_query_limit():
    """Test Query.limit()."""
    User._instances.clear()
    User._next_id = 1
    
    for i in range(10):
        User(name=f"User{i}").save_sync()
    
    results = Query(User).limit(3).all_sync()
    assert len(results) == 3


def test_query_offset():
    """Test Query.offset()."""
    User._instances.clear()
    User._next_id = 1
    
    User(name="User1").save_sync()
    User(name="User2").save_sync()
    User(name="User3").save_sync()
    
    results = Query(User).offset(1).all_sync()
    assert len(results) == 2


def test_query_order_by():
    """Test Query.order_by()."""
    User._instances.clear()
    User._next_id = 1
    
    User(name="Charlie", age=30).save_sync()
    User(name="Alice", age=25).save_sync()
    User(name="Bob", age=35).save_sync()
    
    results = Query(User).order_by("age").all_sync()
    assert results[0].age == 25
    assert results[1].age == 30
    assert results[2].age == 35


def test_query_first():
    """Test Query.first()."""
    User._instances.clear()
    User._next_id = 1
    
    User(name="First").save_sync()
    User(name="Second").save_sync()
    
    result = Query(User).first_sync()
    assert result is not None
    assert result.name in ["First", "Second"]


def test_query_count():
    """Test Query.count()."""
    User._instances.clear()
    User._next_id = 1
    
    User(name="User1", age=25).save_sync()
    User(name="User2", age=30).save_sync()
    User(name="User3", age=25).save_sync()
    
    count = Query(User).where(age=25).count_sync()
    assert count == 2


def test_query_exists():
    """Test Query.exists()."""
    User._instances.clear()
    User._next_id = 1
    
    assert Query(User).exists_sync() is False
    
    User(name="Test").save_sync()
    
    assert Query(User).exists_sync() is True


def test_bulk_create():
    """Test bulk create."""
    User._instances.clear()
    User._next_id = 1
    
    users_data = [
        {"name": "User1", "email": "user1@example.com"},
        {"name": "User2", "email": "user2@example.com"},
        {"name": "User3", "email": "user3@example.com"},
    ]
    
    created = User.bulk_create_sync(users_data)
    
    assert len(created) == 3
    assert User.count_sync() == 3
