"""Empirical Probe Suite for Milestone 3 Iteration 2 Challenger.

Author: teamwork_preview_challenger_m3_iter2_1
Mission: Milestone 3 Iteration 2 - Adversarial Query & Semantic Stress Testing
Verifies:
1. Elimination of collisions on "AEC pricing norms" and "database precision".
2. Ranking purity: Zero foreign records (FreeExile, VoLamWeb) rank above DSCons facts on DSCons domain queries.
3. Zero legacy remnants appear.
4. Top-1 scores, margins, and Recall@3 performance across Vietnamese and English.
"""

import asyncio
import json
import sys
from typing import Any, Dict, List

import pytest
from mcp.client.session import ClientSession
from mcp.client.sse import sse_client

if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(encoding="utf-8", errors="replace")
if hasattr(sys.stderr, "reconfigure"):
    sys.stderr.reconfigure(encoding="utf-8", errors="replace")

MEM0_SSE_URL = "http://127.0.0.1:8765/sse"

PROBE_QUERIES = [
    {"name": "AEC pricing norms", "query": "AEC pricing norms", "expected_code": "RULE-AEC-02"},
    {"name": "database precision", "query": "database precision", "expected_code": "RULE-BACKEND-02"},
    {"name": "CAD takeoff geometry", "query": "CAD takeoff geometry", "expected_code": "RULE-AEC-07"},
    {"name": "quy tắc DSCons", "query": "quy tắc DSCons", "expected_code": "RULE-ROOT-01"},
    {"name": "giao diện dark slate", "query": "giao diện dark slate", "expected_code": "RULE-FRONTEND-01"},
    {"name": "kiến trúc backend", "query": "kiến trúc backend", "expected_code": "RULE-BACKEND-01"},
    {"name": "DSCons rule", "query": "DSCons rule", "expected_code": "RULE-ROOT-01"},
    {"name": "frontend theme", "query": "frontend theme", "expected_code": "RULE-FRONTEND-01"},
    {"name": "backend architecture", "query": "backend architecture", "expected_code": "RULE-BACKEND-01"},
    {"name": "testing workflow", "query": "testing workflow", "expected_code": "RULE-WORKFLOW-01"},
    {"name": "MCP tools protocol", "query": "MCP tools protocol", "expected_code": "RULE-ROOT-04"},
    {"name": "định mức cừ larsen VL=0", "query": "định mức cừ larsen VL=0", "expected_code": "RULE-AEC-02"},
    {"name": "tỷ trọng MR/T", "query": "tỷ trọng MR/T", "expected_code": "RULE-AEC-03"},
    {"name": "bóc tách CAD TCVN3", "query": "bóc tách CAD TCVN3", "expected_code": "RULE-AEC-07"},
    {"name": "deep matrix task.md", "query": "deep matrix task.md", "expected_code": "RULE-WORKFLOW-02"},
    {"name": "hexagonal backend architecture", "query": "hexagonal backend architecture", "expected_code": "RULE-BACKEND-01"},
    {"name": "frontend color palette", "query": "frontend color palette", "expected_code": "RULE-FRONTEND-01"},
    {"name": "dark slate ERP UI", "query": "dark slate ERP UI", "expected_code": "RULE-FRONTEND-01"},
]

FORBIDDEN_LEGACY_STRINGS = [
    "cache 71 hạng mục",
    "4.753 tỷ",
    "app/core/logging_config",
]


def is_dscons_record(hit: Dict[str, Any]) -> bool:
    meta = hit.get("metadata") or {}
    proj = str(meta.get("project", "")).strip().lower()
    mem = str(hit.get("memory", "")).strip()
    return proj == "dscons" or mem.startswith("[DSCons") or "Công ty TNHH Xây Dựng Định Sơn" in mem


@pytest.mark.asyncio
async def test_empirical_challenger_m3_iter2_adversarial_queries():
    async with sse_client(MEM0_SSE_URL) as (r, w):
        async with ClientSession(r, w) as session:
            await session.initialize()

            # 1. Health check
            st = json.loads((await session.call_tool("mem0_status", {})).content[0].text)
            assert st.get("status") == "online"
            assert st.get("developer_memories_count") == 476, f"Expected 476, got {st.get('developer_memories_count')}"

            # 2. Check all 27 DSCons facts presence & integrity
            all_res = json.loads((await session.call_tool("mem0_get_all", {"user_id": "developer", "limit": 1000})).content[0].text)
            all_mems = all_res.get("memories", {}).get("results", [])
            dscons_mems = [m for m in all_mems if is_dscons_record(m)]
            assert len(dscons_mems) == 27, f"Expected 27 DSCons facts, got {len(dscons_mems)}"

            # 3. Legacy string check across all memories
            legacy_found = []
            for m in all_mems:
                t = m.get("memory", "").lower()
                for leg in FORBIDDEN_LEGACY_STRINGS:
                    if leg.lower() in t:
                        legacy_found.append((m.get("id"), leg))
            assert len(legacy_found) == 0, f"Found legacy remnants: {legacy_found}"

            # 4. Probe queries in both unscoped and scoped modes
            for pq in PROBE_QUERIES:
                q = pq["query"]
                for mode in ["unscoped", "scoped"]:
                    args = {"query": q, "user_id": "developer", "limit": 5}
                    if mode == "scoped":
                        args["project"] = "DSCons"

                    resp = await session.call_tool("mem0_search", arguments=args)
                    data = json.loads(resp.content[0].text)
                    hits = data.get("memories", {}).get("results", [])

                    assert len(hits) > 0, f"Query '{q}' returned no hits in {mode} mode"
                    top1 = hits[0]
                    top1_score = float(top1.get("score", 0.0))
                    top1_dscons = is_dscons_record(top1)

                    assert top1_dscons, f"Query '{q}' in {mode} mode returned non-DSCons Top-1 record: {top1.get('memory', '')[:80]}"
                    assert top1_score >= 0.55, f"Query '{q}' in {mode} mode scored {top1_score:.4f} < 0.55"


if __name__ == "__main__":
    asyncio.run(test_empirical_challenger_m3_iter2_adversarial_queries())
