#!/usr/bin/env python3
"""
Tests for Story 1.03: Redis Key Schema
Black Box + White Box + Integration tests

Story: 1.03
Track: A — AIVA RLM Nexus
Module: core/schema/redis_schema.py
"""
import sys
sys.path.insert(0, '/mnt/e/genesis-system')


def test_redis_schema():
    from core.schema.redis_schema import RedisKeySchema, build_key, validate_key, get_ttl

    schema = RedisKeySchema()

    # --- BLACK BOX TESTS ---

    # BB1: build_key with all required fields
    key = build_key(schema.AIVA_WORKING_STATE, session_id="abc123")
    assert key == "aiva:state:abc123", f"Expected aiva:state:abc123, got {key}"

    # BB2: build_key with missing field raises ValueError
    try:
        build_key(schema.AIVA_WORKING_STATE)
        assert False, "Should have raised ValueError"
    except ValueError:
        pass

    # BB3: validate_key with known pattern returns True
    assert validate_key("aiva:state:abc123") is True
    assert validate_key("unknown:key") is False

    # BB4: build_key works for all 8 schema patterns
    assert build_key(schema.AIVA_TRANSCRIPT, session_id="s1") == "aiva:transcript:s1"
    assert build_key(schema.AIVA_CONTEXT_PRELOAD, session_id="s1") == "aiva:context:s1"
    assert build_key(schema.GENESIS_STAGING, task_id="t1") == "genesis:staging:t1"
    assert build_key(schema.GENESIS_MASTER_STATE, session_id="s1") == "genesis:state:master:s1"
    assert build_key(schema.GENESIS_SWARM_TASKS) == "genesis:royal:swarm_tasks"
    assert build_key(schema.AIVA_RESULTS, session_id="s1") == "aiva:results:s1"
    assert build_key(schema.KINAN_ACTIVE_DIRECTIVES) == "kinan:directives:active"

    # BB5: validate_key rejects malformed keys
    assert validate_key("aiva:state:abc 123") is False   # space not allowed
    assert validate_key("aiva:state:abc/123") is False   # slash not allowed
    assert validate_key("AIVA:STATE:ABC123") is False    # uppercase rejected

    # --- WHITE BOX TESTS ---

    # WB1: TTL map returns correct values for timed keys
    assert get_ttl(schema.AIVA_WORKING_STATE) == 86400
    assert get_ttl(schema.AIVA_TRANSCRIPT) == 3600
    assert get_ttl(schema.AIVA_CONTEXT_PRELOAD) == 300
    assert get_ttl(schema.GENESIS_STAGING) == 600

    # WB2: Persistent keys return None (no TTL)
    assert get_ttl(schema.GENESIS_SWARM_TASKS) is None
    assert get_ttl(schema.KINAN_ACTIVE_DIRECTIVES) is None
    assert get_ttl(schema.GENESIS_MASTER_STATE) is None   # not in TTL map
    assert get_ttl(schema.AIVA_RESULTS) is None           # pub/sub, no TTL

    # WB3: build_key with extra fields does not fail (str.format ignores extras)
    key = build_key(schema.AIVA_WORKING_STATE, session_id="abc", extra="ignored")
    assert key == "aiva:state:abc"

    # WB4: validate_key partial match returns False
    assert validate_key("aiva:state:") is False   # empty session_id
    assert validate_key("aiva:state") is False    # missing colon+id

    # WB5: Compiled patterns enforce strict anchoring (^ and $)
    assert validate_key("prefix:aiva:state:abc123") is False   # prefix rejected
    assert validate_key("aiva:state:abc123:suffix") is False   # suffix rejected

    # --- INTEGRATION TESTS ---

    # IT1: Import via __init__.py package works cleanly
    from core.schema import RedisKeySchema as RSK, build_key as bk, validate_key as vk, get_ttl as gt
    s = RSK()
    assert bk(s.AIVA_WORKING_STATE, session_id="it_test") == "aiva:state:it_test"
    assert vk("aiva:state:it_test") is True
    assert gt(s.AIVA_WORKING_STATE) == 86400

    # IT2: Frozen dataclass — cannot mutate schema constants
    try:
        schema.AIVA_WORKING_STATE = "mutated"
        assert False, "Should have raised FrozenInstanceError"
    except Exception:
        pass

    # IT3: All 8 named constants are accessible on schema instance
    constants = [
        'AIVA_WORKING_STATE', 'AIVA_TRANSCRIPT', 'AIVA_CONTEXT_PRELOAD',
        'GENESIS_STAGING', 'GENESIS_MASTER_STATE', 'GENESIS_SWARM_TASKS',
        'AIVA_RESULTS', 'KINAN_ACTIVE_DIRECTIVES',
    ]
    for c in constants:
        assert hasattr(schema, c), f"Missing constant: {c}"

    # IT4: All 4 TTL constants are accessible
    ttl_constants = ['TTL_WORKING_STATE', 'TTL_TRANSCRIPT', 'TTL_CONTEXT_PRELOAD', 'TTL_STAGING']
    for c in ttl_constants:
        assert hasattr(schema, c), f"Missing TTL constant: {c}"

    print("ALL TESTS PASSED — Story 1.03 (9 BB + WB + IT groups)")


if __name__ == "__main__":
    test_redis_schema()
