"""Core tests for cdn-ai package."""

import pytest
from cdn import encode, decode, encode_with_stats, count_tokens, tokenize
from cdn import CondensaEncoder, CondensaDecoder


class TestEncode:
    """Test NL → Condensa encoding."""

    def test_basic_search(self):
        result = encode("Search the web for SpaceX news")
        assert "srch" in result
        assert result.startswith("!")

    def test_filter(self):
        result = encode("Filter active users and sort descending")
        assert "filt" in result

    def test_error(self):
        result = encode("Error: the API returned a 429")
        assert result.startswith("E:")
        assert "429" in result

    def test_cancel(self):
        result = encode("Cancel all running tasks and discard partial results")
        assert result.startswith("X:")
        assert "discard" in result.lower() or "discard:T" in result

    def test_status(self):
        result = encode("Processing complete. 4 out of 4 stages done.")
        assert "#:" in result
        assert "done" in result

    def test_workflow(self):
        result = encode(
            "First, read the data. Then, filter active records. "
            "After that, group by region."
        )
        assert "seq(" in result or "|" in result

    def test_urgency_critical(self):
        result = encode("CRITICAL: drop everything and execute shutdown")
        assert "+++" in result

    def test_urgency_high(self):
        result = encode("Urgent: search for security patches immediately")
        assert "++" in result

    def test_encode_returns_string(self):
        result = encode("Do something")
        assert isinstance(result, str)
        assert len(result) > 0


class TestDecode:
    """Test Condensa → NL decoding."""

    def test_command(self):
        result = decode("!:srch 'SpaceX' /n:5")
        assert "search" in result.lower() or "srch" in result.lower()

    def test_sync_command_v03(self):
        result = decode("!?:read user_profile /timeout:10s fb:cache")
        assert "synchronous" in result.lower() or "sync" in result.lower()

    def test_sync_command_v02_compat(self):
        result = decode("!!:read user_profile /timeout:10s")
        assert "synchronous" in result.lower() or "sync" in result.lower()

    def test_error(self):
        result = decode("E:429 retry:3 wait:30s backoff:exp fb:degrade")
        assert "429" in result
        assert "retry" in result.lower()

    def test_status_done(self):
        result = decode("#:done 4/4 records:12847 fail:0")
        assert "completed" in result.lower() or "done" in result.lower()

    def test_cancel(self):
        result = decode("X: all discard:T")
        assert "cancel" in result.lower()

    def test_update(self):
        result = decode("~:^ s1:keep s2:revise+detail s3:del")
        assert "keep" in result.lower()
        assert "revise" in result.lower()

    def test_pipeline(self):
        result = decode("!:filt status:active | grp region | avg revenue")
        assert "pipeline" in result.lower() or "→" in result

    def test_pipeline_bare_verbs(self):
        """v0.2+ implicit verb mode — bare verbs after first step."""
        result = decode("!:filt active | grp region | avg revenue | sort /desc")
        assert "pipeline" in result.lower() or "→" in result

    def test_policy(self):
        result = decode("@:policy retry:3 timeout:30s fb:degrade")
        assert "session" in result.lower() or "policy" in result.lower() or "default" in result.lower()

    def test_meta(self):
        result = decode("@:define QRS 'read|filt|grp|agg'")
        assert "define" in result.lower()

    def test_delegate(self):
        result = decode(">:@AgentC review code")
        assert "delegate" in result.lower()

    def test_result_with_confidence(self):
        result = decode("=:42 !")
        assert "42" in result

    def test_urgency_prefix(self):
        result = decode("+++!:exec shutdown")
        assert "critical" in result.lower()

    def test_modifiers(self):
        result = decode("!:srch 'query' /n:5 /fmt:json /since:7d")
        assert "5" in result
        assert "json" in result.lower()

    def test_fallback(self):
        result = decode("!:read data fb:cache")
        assert "cache" in result.lower()

    def test_each_modifier_v03(self):
        """v0.3 /each modifier."""
        result = decode("!:sumz results /each")
        assert "each" in result.lower()

    def test_decode_returns_string(self):
        result = decode("!:srch test")
        assert isinstance(result, str)


class TestEncodeWithStats:
    """Test encoding with compression statistics."""

    def test_returns_dict(self):
        result = encode_with_stats("Search for SpaceX news")
        assert isinstance(result, dict)

    def test_has_required_keys(self):
        result = encode_with_stats("Search for SpaceX news")
        assert "original" in result
        assert "condensa" in result
        assert "nl_tokens" in result
        assert "condensa_tokens" in result
        assert "reduction_pct" in result

    def test_compression_positive(self):
        result = encode_with_stats(
            "Please search the web for the latest news about SpaceX Starship "
            "and give me a summary of the top 5 results"
        )
        assert result["reduction_pct"] > 0

    def test_token_counts_positive(self):
        result = encode_with_stats("Search for something")
        assert result["nl_tokens"] > 0
        assert result["condensa_tokens"] > 0


class TestUtils:
    """Test utility functions."""

    def test_count_tokens(self):
        n = count_tokens("hello world")
        assert isinstance(n, int)
        assert n > 0

    def test_count_tokens_empty(self):
        assert count_tokens("") == 0

    def test_tokenize(self):
        tokens = tokenize("hello world")
        assert isinstance(tokens, list)
        assert len(tokens) > 0
        assert all(isinstance(t, str) for t in tokens)


class TestRoundTrip:
    """Test encode → decode round-trip preserves meaning."""

    @pytest.mark.parametrize("condensa_msg", [
        "!:srch 'SpaceX' /n:5",
        "E:429 retry:3 fb:degrade",
        "#:done 4/4 records:100",
        "X: all discard:T",
        "~:^ s1:keep s2:del",
        "@:policy retry:3 timeout:30s",
    ])
    def test_decode_does_not_crash(self, condensa_msg):
        """Every valid Condensa message should decode without error."""
        result = decode(condensa_msg)
        assert isinstance(result, str)
        assert len(result) > 0


class TestBackwardCompatibility:
    """Ensure v0.1 and v0.2 syntax still works."""

    def test_v01_full_pipeline(self):
        """v0.1: explicit !: on every step."""
        result = decode("!:filt active | !:grp region | !:avg revenue")
        assert "pipeline" in result.lower() or "→" in result

    def test_v02_sync_bang_bang(self):
        """v0.2: !! sync command still decodes."""
        result = decode("!!:read profile /timeout:5s")
        assert "synchronous" in result.lower() or "sync" in result.lower()

    def test_v02_fallback_fb(self):
        """fb: fallback works across all versions."""
        result = decode("!:read data fb:cache")
        assert "cache" in result.lower()
