# tests/unit/models/schema/test_auth.py
"""Unit tests for auth Pydantic schemas."""

import pytest
from pydantic import ValidationError

from app.modules.tenancy.schemas.auth import (
    UserCreate,
    UserLogin,
    UserResponse,
    UserUpdate,
)


@pytest.mark.unit
@pytest.mark.schema
class TestUserLoginSchema:
    """Test UserLogin schema validation."""

    def test_valid_login(self):
        """Test valid login data."""
        login = UserLogin(
            email_or_username="testuser",
            password="password123",  # noqa: SEC001
        )
        assert login.email_or_username == "testuser"
        assert login.password == "password123"  # noqa: SEC001

    def test_login_with_email(self):
        """Test login with email."""
        login = UserLogin(
            email_or_username="test@example.com",
            password="password123",  # noqa: SEC001
        )
        assert login.email_or_username == "test@example.com"

    def test_login_with_store_code(self):
        """Test login with optional store code."""
        login = UserLogin(
            email_or_username="testuser",
            password="password123",  # noqa: SEC001
            store_code="STORE001",
        )
        assert login.store_code == "STORE001"

    def test_email_or_username_stripped(self):
        """Test email_or_username is stripped of whitespace."""
        login = UserLogin(
            email_or_username="  testuser  ",
            password="password123",  # noqa: SEC001
        )
        assert login.email_or_username == "testuser"


@pytest.mark.unit
@pytest.mark.schema
class TestUserCreateSchema:
    """Test UserCreate schema validation."""

    def test_valid_user_create(self):
        """Test valid user creation data."""
        user = UserCreate(
            email="admin@example.com",
            username="adminuser",
            password="securepass",  # noqa: SEC001
            first_name="Admin",
            last_name="User",
            role="super_admin",
        )
        assert user.email == "admin@example.com"
        assert user.role == "super_admin"

    def test_default_role_is_store_member(self):
        """Test default role is store_member."""
        user = UserCreate(
            email="store@example.com",
            username="storeuser",
            password="securepass",  # noqa: SEC001
        )
        assert user.role == "store_member"

    def test_invalid_role(self):
        """Test invalid role raises ValidationError."""
        with pytest.raises(ValidationError) as exc_info:
            UserCreate(
                email="test@example.com",
                username="testuser",
                password="securepass",  # noqa: SEC001
                role="superadmin",
            )
        assert "role" in str(exc_info.value).lower()

    def test_username_too_short(self):
        """Test username shorter than 3 characters raises ValidationError."""
        with pytest.raises(ValidationError) as exc_info:
            UserCreate(
                email="test@example.com",
                username="ab",
                password="securepass",  # noqa: SEC001
            )
        assert "username" in str(exc_info.value).lower()

    def test_password_min_length(self):
        """Test password minimum length validation."""
        with pytest.raises(ValidationError) as exc_info:
            UserCreate(
                email="test@example.com",
                username="testuser",
                password="12345",  # noqa: SEC001
            )
        assert "password" in str(exc_info.value).lower()


@pytest.mark.unit
@pytest.mark.schema
class TestUserUpdateSchema:
    """Test UserUpdate schema validation."""

    def test_partial_update(self):
        """Test partial update with only some fields."""
        update = UserUpdate(first_name="NewName")
        assert update.first_name == "NewName"
        assert update.username is None
        assert update.email is None

    def test_username_update_normalized(self):
        """Test username in update is normalized."""
        update = UserUpdate(username="NewUser")
        assert update.username == "newuser"

    def test_invalid_role_update(self):
        """Test invalid role in update raises ValidationError."""
        with pytest.raises(ValidationError):
            UserUpdate(role="superadmin")

    def test_valid_role_update(self):
        """Test valid role values."""
        admin_update = UserUpdate(role="super_admin")
        store_update = UserUpdate(role="merchant_owner")
        assert admin_update.role == "super_admin"
        assert store_update.role == "merchant_owner"

    def test_empty_update(self):
        """Test empty update is valid (all fields optional)."""
        update = UserUpdate()
        assert update.model_dump(exclude_unset=True) == {}


@pytest.mark.unit
@pytest.mark.schema
class TestUserResponseSchema:
    """Test UserResponse schema."""

    def test_from_dict(self):
        """Test creating response from dict."""
        from datetime import datetime

        data = {
            "id": 1,
            "email": "test@example.com",
            "username": "testuser",
            "role": "merchant_owner",
            "is_active": True,
            "created_at": datetime.now(),
            "updated_at": datetime.now(),
        }
        response = UserResponse(**data)
        assert response.id == 1
        assert response.email == "test@example.com"
        assert response.is_active is True

    def test_optional_last_login(self):
        """Test last_login is optional."""
        from datetime import datetime

        data = {
            "id": 1,
            "email": "test@example.com",
            "username": "testuser",
            "role": "merchant_owner",
            "is_active": True,
            "created_at": datetime.now(),
            "updated_at": datetime.now(),
        }
        response = UserResponse(**data)
        assert response.last_login is None
