import unittest
from analogai.foundation.modules.user.user_service import UserService
from analogai.foundation.modules.user.user import User
from analogai.foundation.tests.functional.storage_cleaner import cleanup_storages
from analogai.foundation.tests.functional.services.setup import ServicesTestConfig

class TestUserService(unittest.TestCase):
    def setUp(self):
        self.config = ServicesTestConfig()
        self.storage_adapter = self.config.storage_adapter
        self.user_repository = self.config.user_repository
        self.user_service = UserService(self.user_repository)
        self.test_user_id = "test_user_123"
        self.nonexistent_user_id = "nonexistent_user_456"
        self.test_authority = 0.8

    def tearDown(self):
        self.config.tear_down()

    def test_find_nonexistent_user(self):
        user = self.user_service.find(self.nonexistent_user_id)
        self.assertIsNone(user)

    def test_create_user(self):
        user = self.user_service.create(self.test_user_id, "Test User", "create_user_test@example.com")
        
        self.assertEqual(user.id, self.test_user_id)
        
        stored_user = self.user_repository.find_by_id(self.test_user_id)
        self.assertEqual(stored_user.id, self.test_user_id)

    def test_find_user(self):
        self.user_service.create(self.test_user_id, "Test User", "find_user_test@example.com")
        
        user = self.user_service.find(self.test_user_id)
        
        self.assertEqual(user.id, self.test_user_id)

    def test_find_by_email(self):
        test_email = "unique_test@example.com"
        self.user_service.create(self.test_user_id, "Test User", test_email)
        
        user = self.user_service.find_by_email(test_email)
        
        self.assertEqual(user.id, self.test_user_id)
        self.assertEqual(user.email, test_email)

    def test_find_by_email_nonexistent(self):
        nonexistent_email = "nonexistent@example.com"
        
        user = self.user_service.find_by_email(nonexistent_email)
        
        self.assertIsNone(user)

    def test_update_user_success(self):
        original_user = self.user_service.create(self.test_user_id, "Original Name", "original@example.com")
        original_user_id = original_user.id
        
        updated_user = User(id=self.test_user_id, name="Updated Name", email="updated@example.com")
        result = self.user_service.update(updated_user)
        
        self.assertEqual(result.id, original_user_id)
        self.assertEqual(result.name, "Updated Name")
        self.assertEqual(result.email, "updated@example.com")
        
        stored_user = self.user_service.find(self.test_user_id)
        self.assertEqual(stored_user.id, original_user_id)
        self.assertEqual(stored_user.name, "Updated Name")
        self.assertEqual(stored_user.email, "updated@example.com")
    
    def test_create_user_with_timezone(self):
        timezone = "Europe/London"
        user = self.user_service.create(self.test_user_id, "Test User", "timezone_test@example.com", timezone=timezone)
        
        self.assertEqual(user.timezone, timezone)
        
        stored_user = self.user_repository.find_by_id(self.test_user_id)
        self.assertEqual(stored_user.timezone, timezone)
    
    def test_user_default_timezone(self):
        user = self.user_service.create(self.test_user_id, "Test User", "default_tz_test@example.com")
        
        self.assertIsNotNone(user.timezone)
        
        stored_user = self.user_repository.find_by_id(self.test_user_id)
        self.assertIsNotNone(stored_user.timezone)
    
    def test_user_with_nationality_and_location(self):
        user = User(
            id=self.test_user_id,
            name="Test User",
            email="full_user_test@example.com",
            nationality="US",
            location="New York"
        )
        self.user_repository.create(user)
        
        stored_user = self.user_repository.find_by_id(self.test_user_id)
        self.assertEqual(stored_user.nationality, "US")
        self.assertEqual(stored_user.location, "New York")
    
    def test_update_user_with_all_fields(self):
        original_user = self.user_service.create(self.test_user_id, "Original Name", "original@example.com")
        
        updated_user = User(
            id=self.test_user_id,
            name="Updated Name",
            email="updated@example.com",
            timezone="Asia/Tokyo",
            nationality="JP",
            location="Tokyo"
        )
        result = self.user_service.update(updated_user)
        
        self.assertEqual(result.name, "Updated Name")
        self.assertEqual(result.email, "updated@example.com")
        self.assertEqual(result.timezone, "Asia/Tokyo")
        self.assertEqual(result.nationality, "JP")
        self.assertEqual(result.location, "Tokyo")
        
        stored_user = self.user_service.find(self.test_user_id)
        self.assertEqual(stored_user.timezone, "Asia/Tokyo")
        self.assertEqual(stored_user.nationality, "JP")
        self.assertEqual(stored_user.location, "Tokyo")

    def test_update_user_not_found(self):
        nonexistent_user = User(id=self.nonexistent_user_id, name="Updated Name", email="updated@example.com")
        
        with self.assertRaises(ValueError) as context:
            self.user_service.update(nonexistent_user)
        
        self.assertEqual(str(context.exception), f"User with ID {self.nonexistent_user_id} not found")

    def test_delete_user(self):
        self.user_service.create(self.test_user_id, "Test User", "delete_user_test@example.com")
        
        user = self.user_service.find(self.test_user_id)
        self.assertIsNotNone(user)
        
        result = self.user_service.delete(self.test_user_id)
        self.assertTrue(result)
        
        deleted_user = self.user_service.find(self.test_user_id)
        self.assertIsNone(deleted_user)

    def test_create_user_with_duplicate_email_raises_error(self):
        duplicate_email = "duplicate@example.com"
        self.user_service.create(self.test_user_id, "First User", duplicate_email)
        
        with self.assertRaises(ValueError) as context:
            self.user_service.create("another_user_id", "Second User", duplicate_email)
        
        self.assertIn("already exists", str(context.exception))
        self.assertIn(duplicate_email, str(context.exception))

if __name__ == '__main__':
    unittest.main() 
