# tests/unit/models/schema/test_marketplace_import_job.py
"""Unit tests for marketplace import job Pydantic schemas."""

import pytest
from pydantic import ValidationError

from app.modules.marketplace.schemas import (
    MarketplaceImportJobListResponse,
    MarketplaceImportJobRequest,
    MarketplaceImportJobResponse,
    MarketplaceImportJobStatusUpdate,
)


@pytest.mark.unit
@pytest.mark.schema
class TestMarketplaceImportJobRequestSchema:
    """Test MarketplaceImportJobRequest schema validation."""

    def test_valid_request(self):
        """Test valid import job request."""
        request = MarketplaceImportJobRequest(
            source_url="https://example.com/products.csv",
            marketplace="Letzshop",
        )
        assert request.source_url == "https://example.com/products.csv"
        assert request.marketplace == "Letzshop"

    def test_source_url_required(self):
        """Test source_url is required."""
        with pytest.raises(ValidationError) as exc_info:
            MarketplaceImportJobRequest(marketplace="Letzshop")
        assert "source_url" in str(exc_info.value).lower()

    def test_source_url_must_be_http_or_https(self):
        """Test source_url must start with http:// or https://."""  # noqa: SEC034
        with pytest.raises(ValidationError) as exc_info:
            MarketplaceImportJobRequest(
                source_url="ftp://example.com/products.csv",
            )
        assert "url" in str(exc_info.value).lower()

    def test_source_url_http_is_valid(self):
        """Test http:// URLs are valid."""  # noqa: SEC034
        request = MarketplaceImportJobRequest(
            source_url="http://example.com/products.csv",
        )
        assert request.source_url == "http://example.com/products.csv"

    def test_source_url_with_leading_whitespace_invalid(self):
        """Test source_url with leading whitespace is invalid (validation before strip)."""
        with pytest.raises(ValidationError) as exc_info:
            MarketplaceImportJobRequest(
                source_url="  https://example.com/products.csv",
            )
        assert "url" in str(exc_info.value).lower()

    def test_marketplace_default(self):
        """Test marketplace defaults to Letzshop."""
        request = MarketplaceImportJobRequest(
            source_url="https://example.com/products.csv",
        )
        assert request.marketplace == "Letzshop"

    def test_marketplace_stripped(self):
        """Test marketplace is stripped of whitespace."""
        request = MarketplaceImportJobRequest(
            source_url="https://example.com/products.csv",
            marketplace="  CustomMarket  ",
        )
        assert request.marketplace == "CustomMarket"

    def test_batch_size_default(self):
        """Test batch_size defaults to 1000."""
        request = MarketplaceImportJobRequest(
            source_url="https://example.com/products.csv",
        )
        assert request.batch_size == 1000

    def test_batch_size_minimum(self):
        """Test batch_size must be >= 100."""
        with pytest.raises(ValidationError) as exc_info:
            MarketplaceImportJobRequest(
                source_url="https://example.com/products.csv",
                batch_size=50,
            )
        assert "batch_size" in str(exc_info.value).lower()

    def test_batch_size_maximum(self):
        """Test batch_size must be <= 10000."""
        with pytest.raises(ValidationError) as exc_info:
            MarketplaceImportJobRequest(
                source_url="https://example.com/products.csv",
                batch_size=15000,
            )
        assert "batch_size" in str(exc_info.value).lower()

    def test_batch_size_valid_range(self):
        """Test batch_size in valid range."""
        request = MarketplaceImportJobRequest(
            source_url="https://example.com/products.csv",
            batch_size=5000,
        )
        assert request.batch_size == 5000


@pytest.mark.unit
@pytest.mark.schema
class TestMarketplaceImportJobResponseSchema:
    """Test MarketplaceImportJobResponse schema."""

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

        data = {
            "job_id": 1,
            "store_id": 1,
            "store_code": "TEST_STORE",
            "store_name": "Test Store",
            "marketplace": "Letzshop",
            "source_url": "https://example.com/products.csv",
            "status": "pending",
            "created_at": datetime.now(),
        }
        response = MarketplaceImportJobResponse(**data)
        assert response.job_id == 1
        assert response.store_code == "TEST_STORE"
        assert response.status == "pending"

    def test_default_counts(self):
        """Test count fields default to 0."""
        from datetime import datetime

        data = {
            "job_id": 1,
            "store_id": 1,
            "store_code": "TEST_STORE",
            "store_name": "Test Store",
            "marketplace": "Letzshop",
            "source_url": "https://example.com/products.csv",
            "status": "completed",
            "created_at": datetime.now(),
        }
        response = MarketplaceImportJobResponse(**data)
        assert response.imported == 0
        assert response.updated == 0
        assert response.total_processed == 0
        assert response.error_count == 0

    def test_optional_timestamps(self):
        """Test optional timestamp fields."""
        from datetime import datetime

        now = datetime.now()
        data = {
            "job_id": 1,
            "store_id": 1,
            "store_code": "TEST_STORE",
            "store_name": "Test Store",
            "marketplace": "Letzshop",
            "source_url": "https://example.com/products.csv",
            "status": "completed",
            "created_at": now,
            "started_at": now,
            "completed_at": now,
        }
        response = MarketplaceImportJobResponse(**data)
        assert response.started_at == now
        assert response.completed_at == now

    def test_error_message_optional(self):
        """Test error_message is optional."""
        from datetime import datetime

        data = {
            "job_id": 1,
            "store_id": 1,
            "store_code": "TEST_STORE",
            "store_name": "Test Store",
            "marketplace": "Letzshop",
            "source_url": "https://example.com/products.csv",
            "status": "failed",
            "created_at": datetime.now(),
            "error_message": "Connection timeout",
        }
        response = MarketplaceImportJobResponse(**data)
        assert response.error_message == "Connection timeout"


@pytest.mark.unit
@pytest.mark.schema
class TestMarketplaceImportJobListResponseSchema:
    """Test MarketplaceImportJobListResponse schema."""

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


@pytest.mark.unit
@pytest.mark.schema
class TestMarketplaceImportJobStatusUpdateSchema:
    """Test MarketplaceImportJobStatusUpdate schema."""

    def test_status_only_update(self):
        """Test update with only status."""
        update = MarketplaceImportJobStatusUpdate(status="processing")
        assert update.status == "processing"
        assert update.imported_count is None

    def test_full_update(self):
        """Test update with all fields."""
        update = MarketplaceImportJobStatusUpdate(
            status="completed",
            imported_count=100,
            updated_count=50,
            error_count=2,
            total_processed=152,
        )
        assert update.imported_count == 100
        assert update.updated_count == 50
        assert update.error_count == 2
        assert update.total_processed == 152

    def test_error_update(self):
        """Test update with error message."""
        update = MarketplaceImportJobStatusUpdate(
            status="failed",
            error_message="File not found",
        )
        assert update.status == "failed"
        assert update.error_message == "File not found"
