import json
import logging
import os
import sys
import time

from colorama import Fore, Style, init

# Init Colorama for cross-platform color support
init(autoreset=True)

# Ensure root is in path
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT_DIR)

from GramAddict.core.qdrant_memory import UIMemoryDB
from GramAddict.core.telepathic_engine import TelepathicEngine

# Mute noisy loggers
logging.getLogger("requests").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)


def colored(text, color, attrs=None):
    c = getattr(Fore, color.upper(), "")
    attr_str = ""
    if attrs and "bold" in attrs:
        attr_str = Style.BRIGHT
    return f"{attr_str}{c}{text}"


class MockArgs:
    def __init__(self):
        self.ai_telepathic_model = "qwen3.5:latest"
        self.ai_telepathic_url = "http://localhost:11434/api/generate"
        self.ai_embedding_model = "nomic-embed-text"
        self.ai_embedding_url = "http://localhost:11434/api/embeddings"
        self.ai_vision_navigation = True
        self.ai_vision_context = True


import base64


class MockDevice:
    def __init__(self):
        self.args = MockArgs()
        self.app_id = "com.instagram.android"

    def screenshot(self):
        # Return a simple 1x1 black pixel PNG to test the True Vision payload mapping
        # without crashing on invalid image data.
        return base64.b64decode(
            "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAXSURBVBhXY3jP4PgfAAWEAziO3O8MAAAAASUVORK5CYII="
        )


from GramAddict.core.config import Config

Config().args = MockArgs()


class BrainDiagnosticRunner:
    """
    Professional diagnostic suite for Live integration testing of the
    Singularity LLM Cognitive Stack and Vector DB (Qdrant) persistence.
    Tested against heavy real-world XML dumps from Instagram.
    """

    def __init__(self):
        self.device = MockDevice()
        self.engine = TelepathicEngine.get_instance()
        self.mem_db = UIMemoryDB()

        # Test Namespaces
        self.intents = {
            "modal": "diagnostics_dismiss_obstacle",
            "ad": "diagnostics_find_sponsored",
            "hallucination": "diagnostics_tap_like_button",
            "unfollow": "diagnostics_tap_following_button",
        }

        # Load heavy real-world XML files
        self.fixtures_dir = os.path.join(ROOT_DIR, "tests", "fixtures")
        self.xmls = {
            "modal": self._load_fixture("blocked_ui.xml"),
            "ad": self._load_fixture("peugeot_ad.xml"),
            "hallucination": self._load_fixture("vlm_hallucination.xml"),
            "unfollow": self._load_fixture("unfollow_list_dump.xml"),
        }

    def _load_fixture(self, filename) -> str:
        path = os.path.join(self.fixtures_dir, filename)
        if not os.path.exists(path):
            raise FileNotFoundError(f"Fixture {filename} completely missing. Cannot run parcours.")
        with open(path, "r", encoding="utf-8") as f:
            return f.read()

    def setup(self):
        print(colored("🧠 STARTING LIVE BRAIN 'PARCOURS' DIAGNOSTICS (Qdrant + Qwen 3.5)", "cyan", attrs=["bold"]))
        if not self.mem_db.is_connected:
            logger.error("❌ Qdrant is offline! Diagnostics cannot proceed.")
            sys.exit(1)

        print(colored("🧹 Initializing diagnostic namespace (clearing old cache)...", "yellow"))
        for intent in self.intents.values():
            pt_id = self.mem_db._deterministic_id(intent)
            self.mem_db._delete_point(pt_id)

    def teardown(self):
        print(colored("🧹 Tearing down diagnostic namespace...", "yellow"))
        for intent in self.intents.values():
            pt_id = self.mem_db._deterministic_id(intent)
            self.mem_db._delete_point(pt_id)
        print(colored("✅ Diagnostics Complete.", "green", attrs=["bold"]))

    def test_modal_trap(self) -> dict:
        """
        Challenge: Find the 'OK' or 'Dismiss' button on a blocking popup.
        """
        xml = self.xmls["modal"]
        intent = self.intents["modal"]
        node = self.engine.find_best_node(xml, intent, min_confidence=0.8, device=self.device)

        if not node:
            print(colored("  ❌ LLM failed to find the dismiss button entirely.", "red"))
            return {"passed": False, "reason": "No node found"}

        semantic = str(node.get("semantic", "")).lower()
        if "try again later" in semantic or "action block" in semantic:
            print(colored("  ❌ LLM selected the title text instead of the dismiss button.", "red"))
            return {"passed": False, "reason": "Selected title instead of button"}

        if "dismiss" in semantic or "ok" in semantic:
            print(colored(f"  ✅ VLM correctly reasoned the popup OK/Dismiss button: {semantic}", "green"))
            return {"passed": True, "reason": f"Found correct button: {semantic}"}

        return {"passed": False, "reason": f"Selected unrelated element: {semantic}"}

    def test_ad_deception(self) -> dict:
        """
        Challenge: Identify if the post is an ad by finding 'Sponsored' text.
        """
        xml = self.xmls["ad"]
        intent = self.intents["ad"]
        node = self.engine.find_best_node(xml, intent, min_confidence=0.8, device=self.device)

        if not node:
            print(colored("  ❌ LLM failed to identify the sponsored indicator.", "red"))
            return {"passed": False, "reason": "Missed sponsored text"}

        semantic = str(node.get("semantic", "")).lower()
        if "sponsored" in semantic:
            print(colored("  ✅ VLM correctly identified the tiny 'Sponsored' label amidst a huge post.", "green"))

            # --- Test Fast Path Recall Sub-Scenario ---
            # Save it
            self.engine.confirm_click(intent)
            self.mem_db.store_memory(intent, xml, node)
            import time

            time.sleep(0.5)
            # Try to grab it again
            start = time.time()
            recall_node = self.engine.find_best_node(xml, intent, min_confidence=0.8, device=self.device)
            dur = time.time() - start
            if recall_node and recall_node.get("source") == "memory":
                print(colored(f"  ✅ [Sub-Test] Instant Qdrant Memory Recall verified! Latency: {dur:.3f}s", "green"))
                return {"passed": True, "reason": "Identified sponsored text and verified memory loop."}
            else:
                print(colored("  ❌ [Sub-Test] Memory recall failed.", "red"))
                return {"passed": False, "reason": "Found ad, but memory persistence failed."}

        return {"passed": False, "reason": f"Picked wrong node: {semantic}"}

    def test_vlm_hallucination(self) -> dict:
        """
        Challenge: Find the like heart icon, ignoring caption text that says 'LIKE'.
        """
        xml = self.xmls["hallucination"]
        intent = self.intents["hallucination"]
        node = self.engine.find_best_node(xml, intent, min_confidence=0.8, device=self.device)

        if not node:
            print(colored("  ❌ LLM failed to find any like button.", "red"))
            return {"passed": False, "reason": "No node found"}

        semantic = str(node.get("semantic", "")).lower()

        is_caption = ("double tap" in semantic or "like" in semantic) and "row feed button" not in semantic
        if is_caption:
            print(colored("  ❌ LLM fell for the semantic hallucination gap and selected the text caption!", "red"))
            return {"passed": False, "reason": "Fell for caption text trap"}

        if "row feed button like" in semantic or "heart" in semantic:
            print(
                colored(
                    "  ✅ VLM successfully ignored the deceptive caption and found the structural like button.", "green"
                )
            )
            return {"passed": True, "reason": "Ignored text trap, clicked structural button"}

        return {"passed": False, "reason": f"Picked unrelated node: {semantic}"}

    def execute_all(self):
        self.setup()
        results = {"timestamp": time.time(), "model": self.device.args.ai_telepathic_model, "scenarios": {}}

        def run_and_log(name, func):
            print(colored(f"\n--- SCENARIO: {name} ---", "magenta"))
            start_time = time.time()
            data = {"passed": False, "reason": "Unknown error", "latency_ms": 0}
            try:
                res = func()
                if isinstance(res, dict):
                    data.update(res)
                elif res is True:
                    data["passed"] = True
            except Exception as e:
                print(colored(f"❌ EXCEPTION: {e}", "red"))
                data["reason"] = str(e)

            dur = time.time() - start_time
            data["latency_ms"] = int(dur * 1000)
            results["scenarios"][name] = data

            if data["passed"]:
                print(colored(f"🏁 {name} completed successfully in {dur:.2f}s", "green"))
            else:
                print(colored(f"🚨 {name} FAILED! (Elapsed: {dur:.2f}s)", "red", attrs=["bold"]))

        run_and_log("The Modal Trap (Blocked UI)", self.test_modal_trap)
        run_and_log("The Ad Deception (Sponsored)", self.test_ad_deception)
        run_and_log("The VLM Hallucination Gap (Text Trap)", self.test_vlm_hallucination)
        self.teardown()

        out_path = os.path.join(ROOT_DIR, "benchmarks", "data", "live_learning_results.json")
        with open(out_path, "w") as f:
            json.dump(results, f, indent=4)
        print(colored(f"\n📄 Saved intensive learning results to: {out_path}", "cyan", attrs=["bold"]))


if __name__ == "__main__":
    runner = BrainDiagnosticRunner()
    runner.execute_all()
