"""Tests for Pydantic schemas.

Tests cover:
- Core schema validation
- v24.0 specific schemas
- Field constraints
- Enum values
"""
from __future__ import annotations

import pytest
from pydantic import ValidationError


# =============================================================================
# Core Schema Tests
# =============================================================================

class TestGraphRequest:
    """Tests for GraphRequest schema."""

    def test_valid_get_request(self):
        """Test valid GET request schema."""
        from src.schemas import GraphRequest, HttpMethod
        
        request = GraphRequest(
            path="me/adaccounts",
            method=HttpMethod.GET,
            params={"fields": "id,name"}
        )
        
        assert request.path == "me/adaccounts"
        assert request.method == HttpMethod.GET

    def test_valid_post_request(self):
        """Test valid POST request schema."""
        from src.schemas import GraphRequest, HttpMethod
        
        request = GraphRequest(
            path="act_123/campaigns",
            method=HttpMethod.POST,
            body={"name": "Campaign"}
        )
        
        assert request.method == HttpMethod.POST
        assert request.body == {"name": "Campaign"}


class TestInsightsRequest:
    """Tests for insights-related request schema."""

    def test_valid_auction_insights_request(self):
        """Test valid auction insights request."""
        from src.schemas import AuctionInsightsRequest
        
        request = AuctionInsightsRequest(
            entity_id="act_123",
            time_range={"since": "2024-01-01", "until": "2024-01-31"}
        )
        
        assert request.entity_id == "act_123"


class TestToolResult:
    """Tests for ToolResult schema."""

    def test_success_result(self):
        """Test successful tool result."""
        from src.schemas import ToolResult
        
        result = ToolResult(ok=True, data={"id": "123"})
        
        assert result.ok is True
        assert result.data == {"id": "123"}
        assert result.error is None

    def test_error_result(self):
        """Test error tool result."""
        from src.schemas import ToolResult
        
        result = ToolResult(ok=False, error={"message": "Failed"})
        
        assert result.ok is False
        assert result.error == {"message": "Failed"}


# =============================================================================
# Campaign Schema Tests
# =============================================================================

class TestCampaignSchemas:
    """Tests for campaign-related schemas."""

    def test_campaign_create_v24_request(self):
        """Test v24 campaign creation request schema."""
        from src.schemas import CampaignCreateV24
        
        request = CampaignCreateV24(
            ad_account_id="act_123",
            name="Test Campaign",
            objective="OUTCOME_TRAFFIC"
        )
        
        assert request.ad_account_id == "act_123"
        assert request.name == "Test Campaign"

    def test_campaign_objective_values(self):
        """Test campaign objective values are accepted."""
        from src.schemas import CampaignCreateV24
        
        # Test common objectives
        for objective in ["OUTCOME_TRAFFIC", "OUTCOME_LEADS", "OUTCOME_SALES"]:
            request = CampaignCreateV24(
                ad_account_id="act_123",
                name="Test",
                objective=objective
            )
            assert request.objective == objective


# =============================================================================
# Audience Schema Tests
# =============================================================================

class TestAudienceSchemas:
    """Tests for audience-related schemas."""

    def test_custom_audience_subtype_enum(self):
        """Test custom audience subtype enum."""
        from src.schemas import CustomAudienceSubtype
        
        assert CustomAudienceSubtype.WEBSITE == "WEBSITE"
        assert CustomAudienceSubtype.LOOKALIKE == "LOOKALIKE"

    def test_create_custom_audience_request(self):
        """Test custom audience creation request."""
        from src.schemas import CreateCustomAudienceRequest, CustomAudienceSubtype
        
        request = CreateCustomAudienceRequest(
            ad_account_id="act_123",
            name="Website Visitors",
            subtype=CustomAudienceSubtype.WEBSITE
        )
        
        assert request.name == "Website Visitors"


# =============================================================================
# v24.0 Schema Tests
# =============================================================================

class TestV24Schemas:
    """Tests for v24.0 specific schemas."""

    def test_lookalike_spec_v24(self):
        """Test LookalikeSpecV24 schema."""
        from src.schemas import LookalikeSpecV24
        
        spec = LookalikeSpecV24(
            origin_audience_id="123",
            ratio=0.05,
            country="US",
            type="similarity"
        )
        
        assert spec.ratio == 0.05
        assert spec.type == "similarity"

    def test_lookalike_spec_ratio_bounds(self):
        """Test ratio bounds are enforced."""
        from src.schemas import LookalikeSpecV24
        
        # Test lower bound
        with pytest.raises(ValidationError):
            LookalikeSpecV24(
                origin_audience_id="123",
                ratio=0.001,  # Too low
                country="US"
            )
        
        # Test upper bound
        with pytest.raises(ValidationError):
            LookalikeSpecV24(
                origin_audience_id="123",
                ratio=0.25,  # Too high
                country="US"
            )

    def test_campaign_create_v24(self):
        """Test CampaignCreateV24 with budget sharing field."""
        from src.schemas import CampaignCreateV24
        
        campaign = CampaignCreateV24(
            ad_account_id="act_123",
            name="v24 Campaign",
            objective="OUTCOME_TRAFFIC",
            is_adset_budget_sharing_enabled=True
        )
        
        assert campaign.is_adset_budget_sharing_enabled is True

    def test_adset_create_v24_placement_soft_opt_out(self):
        """Test AdSetCreateV24 with placement_soft_opt_out."""
        from src.schemas import AdSetCreateV24
        
        adset = AdSetCreateV24(
            ad_account_id="act_123",
            campaign_id="campaign_123",
            name="v24 AdSet",
            optimization_goal="REACH",
            targeting={"geo_locations": {"countries": ["US"]}},
            placement_soft_opt_out=["instagram_stream"]
        )
        
        assert "instagram_stream" in adset.placement_soft_opt_out


# =============================================================================
# Enum Tests
# =============================================================================

class TestEnums:
    """Tests for enum types."""

    def test_http_method_enum(self):
        """Test HttpMethod enum."""
        from src.schemas import HttpMethod
        
        assert HttpMethod.GET == "GET"
        assert HttpMethod.POST == "POST"
        assert HttpMethod.DELETE == "DELETE"

    def test_graph_body_encoding_enum(self):
        """Test GraphBodyEncoding enum."""
        from src.schemas import GraphBodyEncoding
        
        assert GraphBodyEncoding.JSON == "json"
        assert GraphBodyEncoding.FORM == "form"

    def test_common_enums_exist(self):
        """Test that common enums can be imported."""
        from src.schemas import (
            HttpMethod,
            GraphBodyEncoding,
            CustomAudienceSubtype,
        )
        # Just verify they exist
        assert HttpMethod is not None
        assert GraphBodyEncoding is not None
        assert CustomAudienceSubtype is not None


# =============================================================================
# Field Constraint Tests
# =============================================================================

class TestFieldConstraints:
    """Tests for field constraints."""

    def test_budget_accepts_value(self):
        """Test budget field accepts numeric value."""
        from src.schemas import AdSetCreateV24
        
        adset = AdSetCreateV24(
            ad_account_id="act_123",
            campaign_id="campaign_123",
            name="Test AdSet",
            optimization_goal="REACH",
            targeting={"geo_locations": {"countries": ["US"]}},
            daily_budget=1000
        )
        
        assert adset.daily_budget == 1000

    def test_account_id_formats(self):
        """Test account IDs accept various formats."""
        from src.schemas import CampaignCreateV24
        
        # With act_ prefix
        req1 = CampaignCreateV24(
            ad_account_id="act_123456789",
            name="Test",
            objective="OUTCOME_TRAFFIC"
        )
        assert req1.ad_account_id == "act_123456789"
