"""Tests that target arrays are stripped from responses to stay under MCP's 1MB limit."""

import json

import pytest

from influ2_mcp.tools.cohorts import _strip_targets_from_response

MCP_SIZE_LIMIT = 1_000_000  # 1MB


def _make_targets(n: int) -> list[dict]:
    """Generate n fake target dicts."""
    return [
        {
            "target_id": f"t-{i}",
            "external_id": f"CRM-{i}",
            "first_name": f"Person{i}",
            "last_name": "Test",
            "email": f"person{i}@example.com",
            "company_name": "Acme Corp",
        }
        for i in range(n)
    ]


class TestStripTargetsFromResponse:
    """Ensure _strip_targets_from_response removes large target arrays safely."""

    def test_strips_top_level_targets(self):
        data = {"cohort_id": "abc", "targets": _make_targets(100)}
        _strip_targets_from_response(data)
        assert "targets" not in data
        assert data["target_count"] == 100

    def test_preserves_sample(self):
        data = {"targets": _make_targets(50)}
        _strip_targets_from_response(data)
        assert len(data["target_sample"]) == 3
        assert data["target_sample"][0]["external_id"] == "CRM-0"

    def test_no_sample_for_empty_targets(self):
        data = {"targets": []}
        _strip_targets_from_response(data)
        assert data["target_count"] == 0
        assert "target_sample" not in data

    def test_strips_nested_targets(self):
        data = {
            "cohort": {
                "name": "Test",
                "targets": _make_targets(500),
            }
        }
        _strip_targets_from_response(data)
        assert "targets" not in data["cohort"]
        assert data["cohort"]["target_count"] == 500

    def test_strips_targets_in_list_items(self):
        data = {
            "contents": [
                {"id": 1, "name": "Ad 1", "targets": _make_targets(200)},
                {"id": 2, "name": "Ad 2", "targets": _make_targets(300)},
            ]
        }
        _strip_targets_from_response(data)
        assert data["contents"][0]["target_count"] == 200
        assert data["contents"][1]["target_count"] == 300
        assert "targets" not in data["contents"][0]

    def test_large_response_under_limit_after_strip(self):
        """5000 targets would be ~750KB raw — must be under 1MB after stripping."""
        data = {
            "cohort": {"cohort_id": "abc", "name": "Big Campaign"},
            "targets": _make_targets(5000),
            "contents": [{"id": 1, "targets": _make_targets(1000)}],
        }
        raw_size = len(json.dumps(data))
        assert raw_size > 500_000, "Test data should be large before stripping"

        _strip_targets_from_response(data)
        stripped_size = len(json.dumps(data))
        assert stripped_size < MCP_SIZE_LIMIT, (
            f"Stripped response {stripped_size:,} bytes exceeds 1MB limit"
        )

    def test_massive_response_under_limit(self):
        """20,000 targets — worst case scenario."""
        data = {"targets": _make_targets(20_000)}
        _strip_targets_from_response(data)
        assert len(json.dumps(data)) < MCP_SIZE_LIMIT

    def test_preserves_non_target_fields(self):
        data = {
            "cohort_id": "abc",
            "name": "Keep Me",
            "status": "active",
            "targets": _make_targets(10),
            "journey": {"stages": [{"name": "warm-up"}]},
        }
        _strip_targets_from_response(data)
        assert data["cohort_id"] == "abc"
        assert data["name"] == "Keep Me"
        assert data["status"] == "active"
        assert data["journey"]["stages"][0]["name"] == "warm-up"

    def test_handles_non_dict_input(self):
        """Should not crash on non-dict input."""
        _strip_targets_from_response("string")
        _strip_targets_from_response(42)
        _strip_targets_from_response(None)
        _strip_targets_from_response([1, 2, 3])

    def test_handles_targets_not_a_list(self):
        """If targets is not a list (e.g., a string or None), leave it alone."""
        data = {"targets": "not a list"}
        _strip_targets_from_response(data)
        assert data["targets"] == "not a list"
