# tests/unit/models/schema/test_vendor.py
"""Unit tests for vendor Pydantic schemas."""
import pytest
from pydantic import ValidationError

from models.schema.vendor import (
    VendorCreate,
    VendorUpdate,
    VendorResponse,
    VendorDetailResponse,
    VendorListResponse,
    VendorSummary,
)


@pytest.mark.unit
@pytest.mark.schema
class TestVendorCreateSchema:
    """Test VendorCreate schema validation."""

    def test_valid_vendor_create(self):
        """Test valid vendor creation data."""
        vendor = VendorCreate(
            company_id=1,
            vendor_code="TECHSTORE",
            subdomain="techstore",
            name="Tech Store",
        )
        assert vendor.company_id == 1
        assert vendor.vendor_code == "TECHSTORE"
        assert vendor.subdomain == "techstore"
        assert vendor.name == "Tech Store"

    def test_company_id_required(self):
        """Test company_id is required."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                vendor_code="TECHSTORE",
                subdomain="techstore",
                name="Tech Store",
            )
        assert "company_id" in str(exc_info.value).lower()

    def test_company_id_must_be_positive(self):
        """Test company_id must be > 0."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=0,
                vendor_code="TECHSTORE",
                subdomain="techstore",
                name="Tech Store",
            )
        assert "company_id" in str(exc_info.value).lower()

    def test_vendor_code_required(self):
        """Test vendor_code is required."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=1,
                subdomain="techstore",
                name="Tech Store",
            )
        assert "vendor_code" in str(exc_info.value).lower()

    def test_vendor_code_uppercase_normalized(self):
        """Test vendor_code is normalized to uppercase."""
        vendor = VendorCreate(
            company_id=1,
            vendor_code="techstore",
            subdomain="techstore",
            name="Tech Store",
        )
        assert vendor.vendor_code == "TECHSTORE"

    def test_vendor_code_min_length(self):
        """Test vendor_code minimum length (2)."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=1,
                vendor_code="T",
                subdomain="techstore",
                name="Tech Store",
            )
        assert "vendor_code" in str(exc_info.value).lower()

    def test_subdomain_required(self):
        """Test subdomain is required."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=1,
                vendor_code="TECHSTORE",
                name="Tech Store",
            )
        assert "subdomain" in str(exc_info.value).lower()

    def test_subdomain_uppercase_invalid(self):
        """Test subdomain with uppercase is invalid (validated before normalization)."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=1,
                vendor_code="TECHSTORE",
                subdomain="TechStore",
                name="Tech Store",
            )
        assert "subdomain" in str(exc_info.value).lower()

    def test_subdomain_valid_format(self):
        """Test subdomain with valid format."""
        vendor = VendorCreate(
            company_id=1,
            vendor_code="TECHSTORE",
            subdomain="tech-store-123",
            name="Tech Store",
        )
        assert vendor.subdomain == "tech-store-123"

    def test_subdomain_invalid_format(self):
        """Test subdomain with invalid characters raises ValidationError."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=1,
                vendor_code="TECHSTORE",
                subdomain="tech_store!",
                name="Tech Store",
            )
        assert "subdomain" in str(exc_info.value).lower()

    def test_name_required(self):
        """Test name is required."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=1,
                vendor_code="TECHSTORE",
                subdomain="techstore",
            )
        assert "name" in str(exc_info.value).lower()

    def test_name_min_length(self):
        """Test name minimum length (2)."""
        with pytest.raises(ValidationError) as exc_info:
            VendorCreate(
                company_id=1,
                vendor_code="TECHSTORE",
                subdomain="techstore",
                name="T",
            )
        assert "name" in str(exc_info.value).lower()

    def test_optional_fields(self):
        """Test optional fields."""
        vendor = VendorCreate(
            company_id=1,
            vendor_code="TECHSTORE",
            subdomain="techstore",
            name="Tech Store",
            description="Best tech store",
            letzshop_csv_url_fr="https://example.com/fr.csv",
            contact_email="contact@techstore.com",
            website="https://techstore.com",
        )
        assert vendor.description == "Best tech store"
        assert vendor.letzshop_csv_url_fr == "https://example.com/fr.csv"
        assert vendor.contact_email == "contact@techstore.com"


@pytest.mark.unit
@pytest.mark.schema
class TestVendorUpdateSchema:
    """Test VendorUpdate schema validation."""

    def test_partial_update(self):
        """Test partial update with only some fields."""
        update = VendorUpdate(name="New Tech Store")
        assert update.name == "New Tech Store"
        assert update.subdomain is None
        assert update.is_active is None

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

    def test_subdomain_normalized_to_lowercase(self):
        """Test subdomain is normalized to lowercase."""
        update = VendorUpdate(subdomain="NewSubdomain")
        assert update.subdomain == "newsubdomain"

    def test_subdomain_stripped(self):
        """Test subdomain is stripped of whitespace."""
        update = VendorUpdate(subdomain="  newsubdomain  ")
        assert update.subdomain == "newsubdomain"

    def test_name_min_length(self):
        """Test name minimum length (2)."""
        with pytest.raises(ValidationError):
            VendorUpdate(name="X")

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

    def test_is_verified_update(self):
        """Test is_verified can be updated."""
        update = VendorUpdate(is_verified=True)
        assert update.is_verified is True

    def test_reset_contact_to_company_flag(self):
        """Test reset_contact_to_company flag."""
        update = VendorUpdate(reset_contact_to_company=True)
        assert update.reset_contact_to_company is True


@pytest.mark.unit
@pytest.mark.schema
class TestVendorResponseSchema:
    """Test VendorResponse schema."""

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

        data = {
            "id": 1,
            "vendor_code": "TECHSTORE",
            "subdomain": "techstore",
            "name": "Tech Store",
            "description": "Best tech store",
            "company_id": 1,
            "letzshop_csv_url_fr": None,
            "letzshop_csv_url_en": None,
            "letzshop_csv_url_de": None,
            "is_active": True,
            "is_verified": False,
            "created_at": datetime.now(),
            "updated_at": datetime.now(),
        }
        response = VendorResponse(**data)
        assert response.id == 1
        assert response.vendor_code == "TECHSTORE"
        assert response.is_active is True


@pytest.mark.unit
@pytest.mark.schema
class TestVendorDetailResponseSchema:
    """Test VendorDetailResponse schema."""

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

        data = {
            "id": 1,
            "vendor_code": "TECHSTORE",
            "subdomain": "techstore",
            "name": "Tech Store",
            "description": None,
            "company_id": 1,
            "letzshop_csv_url_fr": None,
            "letzshop_csv_url_en": None,
            "letzshop_csv_url_de": None,
            "is_active": True,
            "is_verified": True,
            "created_at": datetime.now(),
            "updated_at": datetime.now(),
            # Additional detail fields
            "company_name": "Tech Corp",
            "owner_email": "owner@techcorp.com",
            "owner_username": "owner",
            "contact_email": "contact@techstore.com",
            "contact_email_inherited": False,
        }
        response = VendorDetailResponse(**data)
        assert response.company_name == "Tech Corp"
        assert response.owner_email == "owner@techcorp.com"
        assert response.contact_email_inherited is False


@pytest.mark.unit
@pytest.mark.schema
class TestVendorListResponseSchema:
    """Test VendorListResponse schema."""

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


@pytest.mark.unit
@pytest.mark.schema
class TestVendorSummarySchema:
    """Test VendorSummary schema."""

    def test_from_dict(self):
        """Test creating summary from dict."""
        data = {
            "id": 1,
            "vendor_code": "TECHSTORE",
            "subdomain": "techstore",
            "name": "Tech Store",
            "company_id": 1,
            "is_active": True,
        }
        summary = VendorSummary(**data)
        assert summary.id == 1
        assert summary.vendor_code == "TECHSTORE"
        assert summary.is_active is True
