# tests/unit/models/schema/test_product.py
"""Unit tests for product Pydantic schemas."""

import pytest
from pydantic import ValidationError

from app.modules.catalog.schemas import (
    ProductCreate,
    ProductListResponse,
    ProductResponse,
    ProductUpdate,
)


@pytest.mark.unit
@pytest.mark.schema
class TestProductCreateSchema:
    """Test ProductCreate schema validation."""

    def test_valid_product_create(self):
        """Test valid product creation data."""
        product = ProductCreate(
            marketplace_product_id=1,
            store_sku="SKU-001",
            price=99.99,
            currency="EUR",
        )
        assert product.marketplace_product_id == 1
        assert product.store_sku == "SKU-001"
        assert product.price == 99.99

    def test_marketplace_product_id_required(self):
        """Test marketplace_product_id is required."""
        with pytest.raises(ValidationError) as exc_info:
            ProductCreate(price=99.99)
        assert "marketplace_product_id" in str(exc_info.value).lower()

    def test_price_must_be_non_negative(self):
        """Test price must be >= 0."""
        with pytest.raises(ValidationError) as exc_info:
            ProductCreate(
                marketplace_product_id=1,
                price=-10.00,
            )
        assert "price" in str(exc_info.value).lower()

    def test_price_zero_is_valid(self):
        """Test price of 0 is valid."""
        product = ProductCreate(
            marketplace_product_id=1,
            price=0,
        )
        assert product.price == 0

    def test_sale_price_must_be_non_negative(self):
        """Test sale_price must be >= 0."""
        with pytest.raises(ValidationError) as exc_info:
            ProductCreate(
                marketplace_product_id=1,
                sale_price=-5.00,
            )
        assert "sale_price" in str(exc_info.value).lower()

    def test_min_quantity_default(self):
        """Test min_quantity defaults to 1."""
        product = ProductCreate(marketplace_product_id=1)
        assert product.min_quantity == 1

    def test_min_quantity_must_be_at_least_1(self):
        """Test min_quantity must be >= 1."""
        with pytest.raises(ValidationError) as exc_info:
            ProductCreate(
                marketplace_product_id=1,
                min_quantity=0,
            )
        assert "min_quantity" in str(exc_info.value).lower()

    def test_max_quantity_must_be_at_least_1(self):
        """Test max_quantity must be >= 1 if provided."""
        with pytest.raises(ValidationError) as exc_info:
            ProductCreate(
                marketplace_product_id=1,
                max_quantity=0,
            )
        assert "max_quantity" in str(exc_info.value).lower()

    def test_is_featured_default(self):
        """Test is_featured defaults to False."""
        product = ProductCreate(marketplace_product_id=1)
        assert product.is_featured is False

    def test_all_optional_fields(self):
        """Test product with all optional fields."""
        product = ProductCreate(
            marketplace_product_id=1,
            store_sku="SKU-001",
            price=100.00,
            sale_price=80.00,
            currency="EUR",
            availability="in_stock",
            condition="new",
            is_featured=True,
            min_quantity=2,
            max_quantity=10,
        )
        assert product.sale_price == 80.00
        assert product.availability == "in_stock"
        assert product.condition == "new"
        assert product.is_featured is True
        assert product.max_quantity == 10


@pytest.mark.unit
@pytest.mark.schema
class TestProductUpdateSchema:
    """Test ProductUpdate schema validation."""

    def test_partial_update(self):
        """Test partial update with only some fields."""
        update = ProductUpdate(price=150.00)
        assert update.price == 150.00
        assert update.store_sku is None
        assert update.is_active is None

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

    def test_price_validation(self):
        """Test price must be >= 0 in update."""
        with pytest.raises(ValidationError):
            ProductUpdate(price=-10.00)

    def test_is_active_update(self):
        """Test is_active can be updated."""
        update = ProductUpdate(is_active=False)
        assert update.is_active is False

    def test_is_featured_update(self):
        """Test is_featured can be updated."""
        update = ProductUpdate(is_featured=True)
        assert update.is_featured is True


@pytest.mark.unit
@pytest.mark.schema
class TestProductResponseSchema:
    """Test ProductResponse schema."""

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

        data = {
            "id": 1,
            "store_id": 1,
            "marketplace_product": {
                "id": 1,
                "marketplace_product_id": "TEST001",  # Required field
                "gtin": "1234567890123",
                "title": "Test Product",
                "description": "A test product",
                "brand": "Test Brand",
                "google_product_category": "Electronics",
                "image_link": "https://example.com/image.jpg",
                "created_at": datetime.now(),
                "updated_at": datetime.now(),
            },
            "store_sku": "SKU-001",
            "price": 99.99,
            "sale_price": None,
            "currency": "EUR",
            "availability": "in_stock",
            "condition": "new",
            "is_featured": False,
            "is_active": True,
            "display_order": 0,
            "min_quantity": 1,
            "max_quantity": None,
            "created_at": datetime.now(),
            "updated_at": datetime.now(),
        }
        response = ProductResponse(**data)
        assert response.id == 1
        assert response.store_id == 1
        assert response.is_active is True

    def test_optional_inventory_fields(self):
        """Test optional inventory summary fields."""
        from datetime import datetime

        data = {
            "id": 1,
            "store_id": 1,
            "marketplace_product": {
                "id": 1,
                "marketplace_product_id": "TEST002",  # Required field
                "gtin": "1234567890123",
                "title": "Test Product",
                "description": None,
                "brand": None,
                "google_product_category": None,
                "image_link": None,
                "created_at": datetime.now(),
                "updated_at": datetime.now(),
            },
            "store_sku": None,
            "price": None,
            "sale_price": None,
            "currency": None,
            "availability": None,
            "condition": None,
            "is_featured": False,
            "is_active": True,
            "display_order": 0,
            "min_quantity": 1,
            "max_quantity": None,
            "created_at": datetime.now(),
            "updated_at": datetime.now(),
            "total_inventory": 100,
            "available_inventory": 80,
        }
        response = ProductResponse(**data)
        assert response.total_inventory == 100
        assert response.available_inventory == 80


@pytest.mark.unit
@pytest.mark.schema
class TestProductListResponseSchema:
    """Test ProductListResponse schema."""

    def test_valid_list_response(self):
        """Test valid list response structure."""
        response = ProductListResponse(
            products=[],
            total=0,
            skip=0,
            limit=10,
        )
        assert response.products == []
        assert response.total == 0
        assert response.skip == 0
        assert response.limit == 10
