"""
Tests for two-mode pricing system (Performance/Standard).

These tests verify that both pricing tiers are properly handled in:
1. QueuedRequest.get_priority_score() - queue.py
2. PriorityQueue._get_tier_multiplier() - queue.py
3. PriorityQueue.get_estimated_wait() - queue.py
4. calculate_price() - queue.py
5. estimate_wait_time() - queue.py
6. QueuedJob.get_dynamic_priority() - scheduler.py
7. JobScheduler.submit() initial_priority - scheduler.py
"""

import pytest

from verlex_server.gateway.core.queue import (
    PRICING,
    PricingTier,
    PriorityQueue,
    QueuedRequest,
    QueueStats,
    calculate_price,
    estimate_wait_time,
)


class TestPerformancePriorityScore:
    """Test PERFORMANCE tier in get_priority_score()."""

    def test_performance_priority_score_is_constant(self):
        """PERFORMANCE should get constant high priority (score = 5)."""
        req = QueuedRequest(
            request_id='test1',
            job_id='job1',
            user_id='user1',
            tier=PricingTier.PERFORMANCE
        )
        score = req.get_priority_score()
        assert score == 5.0, f"PERFORMANCE score should be 5, got {score}"


class TestStandardPriorityScore:
    """Test STANDARD tier in get_priority_score()."""

    def test_standard_priority_score_starts_high(self):
        """STANDARD should start with low priority (score ~100)."""
        req = QueuedRequest(
            request_id='test1',
            job_id='job1',
            user_id='user1',
            tier=PricingTier.STANDARD
        )
        score = req.get_priority_score()
        assert 95 <= score <= 105, f"STANDARD score should start ~100, got {score}"


class TestTierMultiplier:
    """Test tier multipliers in PriorityQueue."""

    def test_performance_multiplier_is_1_50(self):
        """PERFORMANCE should use 1.50 multiplier (50% margin)."""
        q = PriorityQueue()
        mult = q._get_tier_multiplier(PricingTier.PERFORMANCE)

        assert mult == PRICING.PERFORMANCE_MULTIPLIER
        assert mult == pytest.approx(1.50), f"Expected 1.50, got {mult}"

    def test_standard_multiplier_is_1_30(self):
        """STANDARD should use 1.30 multiplier (30% margin)."""
        q = PriorityQueue()
        mult = q._get_tier_multiplier(PricingTier.STANDARD)

        assert mult == PRICING.STANDARD_MULTIPLIER
        assert mult == pytest.approx(1.30), f"Expected 1.30, got {mult}"


class TestCalculatePrice:
    """Test calculate_price() with both tiers."""

    def test_performance_adds_50_percent(self):
        """PERFORMANCE should add 50% to base price."""
        base = 1.00
        price, breakdown = calculate_price(base, PricingTier.PERFORMANCE, 0.5)

        assert breakdown["tier_multiplier"] == pytest.approx(1.50), (
            f"Expected tier_multiplier 1.50, got {breakdown['tier_multiplier']}"
        )

    def test_standard_adds_30_percent(self):
        """STANDARD should add 30% to base price."""
        base = 1.00
        price, breakdown = calculate_price(base, PricingTier.STANDARD, 0.5)

        assert breakdown["tier_multiplier"] == pytest.approx(1.30), (
            f"Expected tier_multiplier 1.30, got {breakdown['tier_multiplier']}"
        )

    def test_performance_tier_description(self):
        """PERFORMANCE should show 'Performance (+50%)' in description."""
        _, breakdown = calculate_price(1.0, PricingTier.PERFORMANCE, 0.5)

        assert "Performance" in breakdown["tier_description"], (
            f"Expected 'Performance' in tier_description, got {breakdown['tier_description']}"
        )
        assert "+50%" in breakdown["tier_description"], (
            f"Expected '+50%' in tier_description, got {breakdown['tier_description']}"
        )

    def test_standard_tier_description(self):
        """STANDARD should show 'Standard (+30%)' in description."""
        _, breakdown = calculate_price(1.0, PricingTier.STANDARD, 0.5)

        assert "Standard" in breakdown["tier_description"], (
            f"Expected 'Standard' in tier_description, got {breakdown['tier_description']}"
        )
        assert "+30%" in breakdown["tier_description"], (
            f"Expected '+30%' in tier_description, got {breakdown['tier_description']}"
        )


class TestEstimateWaitTime:
    """Test estimate_wait_time() with both tiers."""

    def test_performance_minimal_wait(self):
        """PERFORMANCE should get near-immediate execution."""
        stats = QueueStats(performance_requests=2, standard_requests=3)
        min_wait, max_wait = estimate_wait_time(PricingTier.PERFORMANCE, stats)

        assert min_wait == 0
        assert max_wait <= 60, f"PERFORMANCE max wait should be <= 60s, got {max_wait}"

    def test_standard_max_10_minutes(self):
        """STANDARD should have max wait of 10 minutes."""
        stats = QueueStats(performance_requests=2, standard_requests=3)
        _, max_wait = estimate_wait_time(PricingTier.STANDARD, stats)

        assert max_wait == 600, f"STANDARD max wait should be 600s, got {max_wait}"


class TestSchedulerDynamicPriority:
    """Test dynamic priority in scheduler.py."""

    def test_scheduler_performance_dynamic_priority(self):
        """PERFORMANCE should get constant high priority in scheduler."""
        from verlex_server.gateway.backend.scheduler import PricingTier as SchedPricingTier
        from verlex_server.gateway.backend.scheduler import QueuedJob

        job = QueuedJob(
            priority_score=5.0,
            submitted_at=1000.0,
            job_id="test",
            user_id="user",
            serialized_function={},
            resources={},
            mode="P",
            config={},
            pricing_tier=SchedPricingTier.PERFORMANCE,
            base_price_per_hour=1.0,
            tier_multiplier=1.50,
            final_price_per_hour=1.50,
        )

        priority = job.get_dynamic_priority()
        assert priority <= 10, f"PERFORMANCE priority should be <=10, got {priority}"

    def test_scheduler_standard_dynamic_priority(self):
        """STANDARD should start with lower priority that improves over time."""
        import time

        from verlex_server.gateway.backend.scheduler import PricingTier as SchedPricingTier
        from verlex_server.gateway.backend.scheduler import QueuedJob

        job = QueuedJob(
            priority_score=100.0,
            submitted_at=time.time(),
            job_id="test",
            user_id="user",
            serialized_function={},
            resources={},
            mode="S",
            config={},
            pricing_tier=SchedPricingTier.STANDARD,
            base_price_per_hour=1.0,
            tier_multiplier=1.30,
            final_price_per_hour=1.30,
        )

        priority = job.get_dynamic_priority()
        # Standard starts at ~100, should be > performance
        assert priority > 5, f"STANDARD priority should be > 5 initially, got {priority}"


class TestCrossModuleConsistency:
    """Test pricing consistency across modules."""

    def test_performance_margin_consistent(self):
        """Performance margin should be 50% everywhere."""
        from decimal import Decimal

        from verlex_server.gateway.backend.billing import GATEWAY_MARGIN_PERCENT, ExecutionMode
        from verlex_server.gateway.core.queue import PRICING
        from verlex_server.gateway.core.selection import PRICING_MULTIPLIERS, SelectionMode

        # queue.py
        queue_mult = PRICING.PERFORMANCE_MULTIPLIER
        assert queue_mult == pytest.approx(1.50), f"queue.py: {queue_mult}"

        # billing.py
        billing_margin = GATEWAY_MARGIN_PERCENT[ExecutionMode.PERFORMANCE]
        assert billing_margin == Decimal("0.50"), f"billing.py: {billing_margin}"

        # selection.py
        selection_mult = PRICING_MULTIPLIERS[SelectionMode.PERFORMANCE]
        assert selection_mult == pytest.approx(1.50), f"selection.py: {selection_mult}"

    def test_standard_margin_consistent(self):
        """Standard margin should be 30% everywhere."""
        from decimal import Decimal

        from verlex_server.gateway.backend.billing import GATEWAY_MARGIN_PERCENT, ExecutionMode
        from verlex_server.gateway.core.queue import PRICING
        from verlex_server.gateway.core.selection import PRICING_MULTIPLIERS, SelectionMode

        # queue.py
        queue_mult = PRICING.STANDARD_MULTIPLIER
        assert queue_mult == pytest.approx(1.30), f"queue.py: {queue_mult}"

        # billing.py
        billing_margin = GATEWAY_MARGIN_PERCENT[ExecutionMode.STANDARD]
        assert billing_margin == Decimal("0.30"), f"billing.py: {billing_margin}"

        # selection.py
        selection_mult = PRICING_MULTIPLIERS[SelectionMode.STANDARD]
        assert selection_mult == pytest.approx(1.30), f"selection.py: {selection_mult}"
