"""
Tests for User model - Task 1 validation
"""

import uuid

import pytest
import pytest_asyncio
from sqlalchemy import select, text
from sqlalchemy.ext.asyncio import AsyncSession

from database.models import User, PlanType


class TestUserModelFields:
    """Test User model has all required fields (AC1)"""

    @pytest.mark.asyncio
    async def test_user_has_tier_field_with_default_free(
        self, async_session: AsyncSession
    ):
        """AC1: User should have tier field with default 'free'"""
        user = User(
            email="test@example.com",
            name="Test User",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        assert user.tier == "free", "Default tier should be 'free'"

    @pytest.mark.asyncio
    async def test_user_tier_can_be_pro(self, async_session: AsyncSession):
        """AC1: User tier can be set to 'pro'"""
        user = User(
            email="pro@example.com",
            name="Pro User",
            hashed_password="hashed_abc123",
            tier="pro",
        )
        async_session.add(user)
        await async_session.commit()

        assert user.tier == "pro"

    @pytest.mark.asyncio
    async def test_user_has_daily_translation_count_default_zero(
        self, async_session: AsyncSession
    ):
        """AC1: User should have daily_translation_count with default 0"""
        user = User(
            email="daily@example.com",
            name="Daily User",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        assert user.daily_translation_count == 0

    @pytest.mark.asyncio
    async def test_user_has_hashed_password_field(self, async_session: AsyncSession):
        """AC1: User should have hashed_password field (renamed from password_hash)"""
        user = User(
            email="hash@example.com",
            name="Hash User",
            hashed_password="hashed_password_value",
        )
        async_session.add(user)
        await async_session.commit()

        assert hasattr(user, "hashed_password")
        assert user.hashed_password == "hashed_password_value"

    @pytest.mark.asyncio
    async def test_user_has_uuid_id(self, async_session: AsyncSession):
        """AC1: User id should be UUID type"""
        user = User(
            email="uuid@example.com",
            name="UUID User",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        assert user.id is not None
        uuid.UUID(user.id)

    @pytest.mark.asyncio
    async def test_user_has_all_base_fields(self, async_session: AsyncSession):
        """AC1: User should have all required base fields"""
        user = User(
            email="base@example.com",
            name="Base User",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        assert user.email == "base@example.com"
        assert user.name == "Base User"
        assert user.created_at is not None
        assert user.updated_at is not None

    @pytest.mark.asyncio
    async def test_user_keeps_deprecated_plan_field_for_compatibility(
        self, async_session: AsyncSession
    ):
        """Task 1.4: Keep existing plan field for backward compatibility"""
        user = User(
            email="compat@example.com",
            name="Compat User",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        assert hasattr(user, "plan"), (
            "plan field should still exist for backward compatibility"
        )


class TestUserModelAsyncOperations:
    """Test async database operations (AC2)"""

    @pytest.mark.asyncio
    async def test_create_user_async(self, async_session: AsyncSession):
        """AC2: Should be able to create user with async session"""
        user = User(
            email="async_create@example.com",
            name="Async Create",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        result = await async_session.execute(
            select(User).where(User.email == "async_create@example.com")
        )
        found_user = result.scalar_one()
        assert found_user.email == "async_create@example.com"

    @pytest.mark.asyncio
    async def test_read_user_async(self, async_session: AsyncSession):
        """AC2: Should be able to read user with async session"""
        user = User(
            email="async_read@example.com",
            name="Async Read",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        result = await async_session.execute(
            select(User).where(User.email == "async_read@example.com")
        )
        found_user = result.scalar_one()
        assert found_user.name == "Async Read"

    @pytest.mark.asyncio
    async def test_update_user_async(self, async_session: AsyncSession):
        """AC2: Should be able to update user with async session"""
        user = User(
            email="async_update@example.com",
            name="Async Update",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        user.tier = "pro"
        user.daily_translation_count = 5
        await async_session.commit()

        result = await async_session.execute(
            select(User).where(User.email == "async_update@example.com")
        )
        updated_user = result.scalar_one()
        assert updated_user.tier == "pro"
        assert updated_user.daily_translation_count == 5

    @pytest.mark.asyncio
    async def test_delete_user_async(self, async_session: AsyncSession):
        """AC2: Should be able to delete user with async session"""
        user = User(
            email="async_delete@example.com",
            name="Async Delete",
            hashed_password="hashed_abc123",
        )
        async_session.add(user)
        await async_session.commit()

        await async_session.delete(user)
        await async_session.commit()

        result = await async_session.execute(
            select(User).where(User.email == "async_delete@example.com")
        )
        assert result.scalar_one_or_none() is None
